bug-bash
[Top][All Lists]
Advanced

[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'.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]