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!
The
ERRtrap fires for "simple commands" a pipeline is not a simple command.It might fire for the result of the whole pipeline (I'm not sure) and you might be able to get something closer to what you want by setting
pipefail.(Note: This is one of the reasons people often don't recommend using
set -eas it has surprising details like this.)The reason
pipefailworks is that normally the return status of a pipeline is the return of the last command but withpipefailon it becomes the return status of the last command that fails.