Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash: Trap ERR does not work when pipe operator is used

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!

like image 616
cristiprg Avatar asked Dec 18 '14 12:12

cristiprg


1 Answers

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.

like image 192
Etan Reisner Avatar answered Sep 23 '22 13:09

Etan Reisner