I am trying to log everything that comes out of stdout and stderr into a log file and still preserve the console. For this, I just appended: |& tee -a log_file.log
to every command.
However, I also want to run a custom command if any error occurred during the script. For this, I added the following at the beginning of the script: trap "echo Non-zero exit code detected" ERR
.
The problem is by using the pipe operator, the echo in the trap does not execute anymore.
Script 1, without pipe:
$cat test.sh
#!/bin/bash
trap "echo Non-zero exit code detected!" ERR
function fail_please()
{
echo "Returning non-zero exit code!"
return 1
}
fail_please
Output 1:
$ ./test.sh
Returning non-zero exit code!
Non-zero exit code detected!
Script 2, with pipe:
$ cat test.sh
#!/bin/bash
trap "echo Non-zero exit code detected!" ERR
function fail_please()
{
echo "Returning non-zero exit code!"
return 1
}
fail_please |& tee log_file.log
Output 2:
$ ./test.sh
Returning non-zero exit code!
$ cat log_file.log
Returning non-zero exit code!
In output 2, the message "Non-zero exit code detected!" is missing. Any idea why? Thanks!
pipefail
. This is one of the reasons people often don't recommend usingset -e
as it has surprising details like this. – Mackeyset -o pipefail
and it worked. However, I didn't quite understand whyset -e
isn't recommended. Does it have other caveats? Also, please add an answer to accept it. – Reactanceset -e
has similar caveats to yourERR
trap. It doesn't fire in all the situations you might expect it to. And some of those situations are external to your otherwise working code. – Mackeypipefail
, the return code of the pipe is still 0 (because tee returns 0), but it enables myERR
trap to fire in case the first command failed. Is this correct? – Reactancepipefail
works to my answer but yes, it sets the return to the exit status of the last command that fails instead of always being the exit status of the last command in the pipeline. – Mackey