1

I have this:

nohup_ntrs(){
  nohup_file="$HOME/teros/nohup/stdio.log"
  mkdir -p "$(dirname "$nohup_file")";
  echo " ------------- BEGIN $(date) -------------- " >> "$nohup_file"
  nohup "$@" &>> "$nohup_file"
  echo " ------------- END $(date) -------------- " >> "$nohup_file"
}

but this syntax is wrong:

 nohup "$@" &>> "$nohup_file"

I was trying to use the >> operator for append but also send stderr there. My guess is that the only way to do this is this:

 nohup "$@" 2>&1 >> "$nohup_file"

is there a less verbose way to do this?

Alexander Mills
  • 9,330
  • 19
  • 95
  • 180

2 Answers2

4

&>> is correct syntax in the bash shell to redirect both the standard output stream and the standard error stream to a file in append mode.

What I think may be happening is that you run the script using sh, which on your system is not bash. Or, you are running a bash older than release 4.0, which is the first release that supported &>>.

The other way to do this, which is standard compliant, is to use >>file 2>&1. In your case,

nohup "$@" >>"$nohup_file" 2>&1

There is no shorter way to do this in a standard compliant sh shell.

Note that what you suggest, 2>&1 >>file, is back to front and would not send the standard error stream to the file but to wherever the standard output stream originally went. Redirections are handled in a left-to-right manner, so your redirection would first send standard error to wherever standard output goes, and then redirect standard output to the file in append mode. In other words: the second redirection, >>file would not change where standard error goes, so it goes where standard output originally went due to the preceding 2>&1.


An alternative way to write your code would be

nohup_ntrs () {
  nohup_file="$HOME/teros/nohup/stdio.log"
  mkdir -p "$(dirname "$nohup_file")"

  {
    printf ' ------------- BEGIN %s -------------- \n' "$(date)"
    nohup "$@"
    printf ' ------------- END %s ---------------- \n' "$(date)"
  } >>"$nohup_file" 2>&1
}

This reduces the number of redirections to a single one by grouping the commands whose output should be redirected in curly braces and redirecting that compound command as a whole.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
  • yeah I guess on bash version 3, the `&>>` operator doesn't work, but bash 4 recognizes it or something – Alexander Mills Aug 07 '19 at 18:17
  • btw, just curious, why does the `2>&1` go after the `>>` operator, not before? I think there is a reason for that but idk – Alexander Mills Aug 07 '19 at 18:18
  • 1
    @AlexanderMills I tried to explain the significance of the ordering. There are other questions on this site regarding this. See e.g. [Order of redirections](//unix.stackexchange.com/q/37660) and [understand a sequence of redirections](//unix.stackexchange.com/q/16360) – Kusalananda Aug 07 '19 at 18:20
0

nohup "$@" 2>&1 | tee "$nohup_file"

Or you can open file descriptor in script with exec and redirect both stdout and stderr to this descriptor

  • This would truncate and overwrite the output file. I think you may have wanted to use `tee -a`. This would, however, arguably not be "less verbose". – Kusalananda Aug 07 '19 at 18:08
  • That's a bit of a useless use of `tee`, but if you do that, you may want to `> /dev/null` it so you don't get the output on the terminal. – ilkkachu Aug 07 '19 at 18:10