[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Error in pipeline ignored when not in last command
From: |
bashbug2eran |
Subject: |
Error in pipeline ignored when not in last command |
Date: |
Sat, 07 Feb 2004 02:17:26 +0200 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.6) Gecko/20040113 |
Bash Version: 2.05b
Patch Level: 0
Release Status: release
Description:
When a command ends with a non-zero status, and this is not the
last command in a pipeline, 'set -e' does not cause the script to
be aborted. Similarly, 'trap handler ERR' does not invoke
the handler. This contradicts the bash manpage, which states that
the only case where a non-zero status is not considered an error
for these purposes is "if the command that fails is part of an
until or while loop, part of an if statement, part of a && or ||
list, or if the command's return value is being inverted via !".
None of this is the case in a pipeline.
Note that the implemented behavior is consistent with the rule that
"the status of the pipeline is the exit status of the last
command", but the rules for 'trap' and 'set -e' explicitly refer to
simple commands, not pipelines.
The documented behavior seems to be more useful than the implemented
behavior: "set -e" is a good quick&dirty way to make sure that in case
something goes wrong the script will stop before doing any harm, and
errors in pipeline are often relevant. As a typical scenario,
consider the following script for creating an incremental backup:
#!/bin/sh
set -e
tar cf - ~/mydata | \
rdiff delta ~/backup/old.sig /dev/stdin ~/backup/new.delta
echo Success
Here, failure of tar will go undetected.
Another real case:
http://mirror.hamakor.org.il/archives/linux-il/10-2003/5991.htm
Repeat-By:
Both of these output DONE instead of nothing:
( set -e; false && true; echo DONE )
( trap "echo ERROR" ERR; false && true; echo DONE )
Workaround:
Check $PIPESTATUS after every nontrivial pipeline:
check() { [[ ${PIPESTATUS[*]} == 0*( 0) ]] || false; }
( set -e; false | true; check; echo DONE )
Of course, this defeats the point of 'set -e'.
- Error in pipeline ignored when not in last command,
bashbug2eran <=