问题
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!
回答1:
The ERR
trap 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 -e
as it has surprising details like this.)
The reason pipefail
works is that normally the return status of a pipeline is the return of the last command but with pipefail
on it becomes the return status of the last command that fails.
The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled. If pipefail is enabled, the pipeline’s return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit success- fully.
来源:https://stackoverflow.com/questions/27546819/bash-trap-err-does-not-work-when-pipe-operator-is-used