Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0000789 [1003.1(2008)/Issue 7] Shell and Utilities Comment Enhancement Request 2013-11-08 16:02 2020-06-12 09:58
Reporter weeks View Status public  
Assigned To ajosey
Priority normal Resolution Accepted As Marked  
Status Applied  
Name Nathan Weeks
Organization USDA-ARS
User Reference
Section 2.9.2
Page Number 2341
Line Number 74464-74467
Interp Status ---
Final Accepted Text Note: 0004103
Summary 0000789: Add set -o pipefail
Description The "set -o pipefail" option is a useful extension that allows the detection
of errors in pipelines where all commands are expected to have a zero exit
status, rather than just the last command; in my experience, this applies to
the majority of pipelines used in shell scripts, making the pipefail option
indispensable for writing robust shell scripts.

The pipefail option was originally implemented in ksh93 back in 1998; has
since been implemented in bash 3.0, busybox sh 1.16.0, and mksh R46; and will
be in zsh 4.0.2. It is notably absent from dash and FreeBSD/NetBSD /bin/sh.
Desired Action It may be clearer to describe the exit status of a pipeline with a table,
since the exit status of a pipeline would now depend on both the pipefail
option in addition to the ! reserved word.

In section 2.9.2, change:

    If the pipeline does not begin with the ! reserved word, the exit status shall
    be the exit status of the last command specified in the pipeline. Otherwise,
    the exit status shall be the logical NOT of the exit status of the last
    command. That is, if the last command returns zero, the exit status shall be 1;
    if the last command returns greater than zero, the exit status shall be zero.

to:

    The exit status of a pipeline shall depending on if the pipefail option is
    enabled, and if the pipeline is preceded by the ! reserved word to return
    the logical NOT of the exit status of the pipeline. The following table
    summarizes the effect of the pipefail option and the ! reserved word:

  pipefail Enabled    Preceded by !      Exit Status

    no                  no             The exit status of the last command
                                       specified in the pipeline.

    no                  yes            Zero, if the last command in
                                       the pipeline returned an exit
                                       status of 0; otherwise, 1.

    yes                 no             Zero, if all commands in the pipeline
                                       returned an exit status of 0;
                                       otherwise, the exit status of the
                                       last command specified in the
                                       pipeline that returned a non-zero
                                       exit status.

    yes                 yes            Zero, if any command in the
                                       pipeline returned a non-zero
                                       exit status; otherwise, 1.


In the description of "set -o option", add:

    pipefail
        When this option is enabled, the exit status of a pipeline shall be the
        exit status of the last command specified in the pipeline to return a
        non-zero exit status, or zero if all commands returned an exit status
        of 0.

It may be beneficial to include a note in this description referencing section
2.9.2, as the behavior of the ! reserved word also influences the exit status
of a pipeline.
Tags issue8
Attached Files

- Relationships
related to 0001207Applied 1003.1(2016/18)/Issue7+TC2 "set -o option" should be mandatory, not UP 
related to 0000267Appliedajosey 1003.1(2004)/Issue 6 time (keyword) 

-  Notes
(0001976)
eblake (manager)
2013-11-08 16:15

If we standardize this, then we need to also take some time to revisit what shell utilities should do when writing to a pipe when the reader closes early. Is it okay for a utility to exit with status 0 even when encountering a SIGPIPE (or EPIPE write() failure if SIGPIPE is ignored), when the utilities main goal is a filter that writes to stdout? Right now, it's perfectly okay for 'grep $pattern largefile | head -n1' to have grep exit with non-zero status because the pattern matched enough lines in largefile that it hits a write failure when head exits early; but if you support a pipefail mode, then grep exiting with non-zero status due to writing to a closed pipe would cause seemingly random behavior (a pipeline may succeed normally, but fail when the system is heavily loaded).
(0001977)
Don Cragun (manager)
2013-11-08 16:57

I merged the attached file containing the table describing the update to a pipeline's exit status into the Desired Action and removed the attached file.
(0001978)
shware_systems (reporter)
2013-11-08 21:05
edited on: 2013-11-12 16:08

Adding set -o implies set +o too... A pipe could be wrapped with set +o pipefail; pipe_and_error_handling; set -o pipefail; easy enough. An application usage blurb that this sort of case needs to be taken into account should be provided, as that is a valid looking concern, but I'm not sure any behavioral changes otherwise are needed. An alternative would be a pipeonce version where this behavior usually off but a set -o pipeonce; pipe; just apples to that pipe.

My concern with this would be: with the current way you know the exit status applies to the last process of the pipe. Just setting an option doesn't provide a way for the script to determine which process errored first so appropriate recovery can be attempted, and the error code should reflect that process. A new special variable would be needed, similar to argument count, to handle that. The proposed behavior, of last error is reported, may be a cascade of simply "Unexpected EOF" rather than "Socket connection timed out" that curl might report as first error.

(0001982)
weeks (reporter)
2013-11-12 15:42

Aside from using "set +o pipefail" to disable pipefail for an entire pipeline,
if it is known beforehand that a command in a pipeline may not read all the
output from the previous command, pipefail can be selectively disabled by
running the affected command(s) in a subshell that ignores SIGPIPE; e.g.:

    grep "$pattern" largefile | (trap '' PIPE; sort) | head -n 1

This allows the grep & sort exit statuses to still influence the exit status
of the entire pipeline, where the sort command may return a non-zero exit
status for reasons other than a SIGPIPE.
(0001983)
eblake (manager)
2013-11-12 15:51

(trap '' PIPE; sort) isolates you from sort dying from SIGPIPE, but does NOT isolate you from sort exiting with non-zero status due to claiming that an EPIPE failure to write() is fatal. Which brings me back to my argument: if we are going to mandate 'set -o pipefail', we also need to standardize on whether utilities must treat EPIPE as fatal (as implied by the current wording on error handling), or whether it makes sense to mandate that some utilities shall treat EPIPE as non-fatal (namely, any utility that has no side effects other than outputting to stdout, where EPIPE is a sign that the reader on the other end no longer cares about that output).
(0002067)
weeks (reporter)
2013-12-11 22:40

Eric: understood; I had completely missed that point in your first response. It may be okay for certain standard utilities to exit with status 0 upon write() failing due to EPIPE, though in that case I don't think it would be okay for such utilities to ignore SIGPIPE by default; this gives the script writer control over whether or not writing to a closed pipe constitutes an error (e.g., using the previously-mentioned workaround if a SIGPIPE is expected).

Even without such a mandate, forcing the "sort" stage in the previous example pipeline to exit with status 0, e.g.:

grep "$pattern" largefile | (sort; true) | head -n 1

is still an improvement over not having the pipefail option at all---at least "grep" can fail and cause the exit status of the pipeline to be nonzero.
(0002107)
shware_systems (reporter)
2014-01-16 23:15

Per phone call 2014-Jan-09, text from Etherpad reflecting discussion points:

Knowing a pipeline failed is not as useful without an array variable of which process(es) in the pipeline failed - both ksh and bash have pipefail, but they also have an array variable extension that gives this extra information
Proposed is an index variable that relates failure code reported to process position in pipe, absent a standardized array capability. Maybe something like 'fail() { return $1; }; fail 2 | : | fail 3' producing "2 0 3" in the new variable. Maybe named POSIX_PIPE_STATUS
Generically, value uses space separated string of the return codes for each member of the pipe in decimal notation. Not discussed, would a new pipe invocation clear prior value, or is it the scripts responsibility to clear it?
Presuming the first, a caveat that a script has to copy the value if error recovery also uses a pipe may be desirable, rather than reference it directly.

A method to check for parent relations may be: call
cat /etc/termcap | cat | ps -f

and then check for PPID in the ps output

Action: Andrew: Ask shell maintainers: Would it be appropriate to add set -o pipefail and set +o pipefail without also adding the arrays that provide the exit status of all processes in the pipeline (or some non-array equivalent; see above)?
Standardizing arrays first may be the higher priority, as arrays offer a lot more benefits than just pipeline status
(0002253)
weeks (reporter)
2014-05-28 15:47

mksh, bash, and zsh implement PIPESTATUS (pipestatus, for zsh) arrays containing the exit statuses of the previous foreground pipeline; however, busybox ash lacks arrays, and ksh does not have an equivalent array of exit statuses.

It would be expedient to first standardize common practice that's portable between the existing implementations ("set -o pipefail" only), then possibly mandate an array of exit statuses if/when arrays are standardized.
(0002685)
stephane (reporter)
2015-05-29 21:14

I find "last" in the proposed text ambiguous as there's a possible confusion between "last" meaning "rightmost" or "last to exit".

In:

set -o pipefail
(sleep 3; exit 3) | (sleep 1; exit 2) | true

$? should be 2 (the rightmost command that exited with a non-zero status), not 3 (the last command to exit with a non-zero exit status after 3 seconds).
(0002689)
stephane (reporter)
2015-05-31 18:27
edited on: 2015-05-31 19:27

IMO, changing utilities so that they return success upon SIGPIPE is out of the question. Think for instance of scripts that should be able to exit early when the command they run dies of a SIGPIPE when stdout is a broken pipe.

#! /bin/sh -
utility1 || exit
echo foo
utility3 || exit
echo bar
...


We could make the pipefail implementation ignore the status of commands that die of SIGPIPE, but then again, deciding what constitutes a SIGPIPE death is not always clear and the decision would be better left to the application.

For instance, in:

   (cmd1; exit) | script2 | cmd3

The first subshell would typically terminate normally with exit code 141 (128+SIGPIPE) if the pipe became broken. Could be the same for script2, though an exit code of 141 could also be caused by an unrelated pipe.

Also, option handling is not really compatible with the function features. Options are better avoided where possible.

For instance in:

set -o pipefail
cmd1 | cmd2 | cmd3
set +o pipefail

If any of those cmd1/2/3 is a function, setting that option could unexpectedly change the behaviour of that function. This kind of issue crops up all the time for other options. For instance, the bash completion system (based on functions) fails when you change some of the default options. Some shells like zsh can alleviate the problem by resetting the options to their default in a local scope, but even then that's cumbersome and not ideal (and there's nothing like that in POSIX sh yet).

Instead I'm suggesting introducing a new builtin to check the pipeline failure which could also address some of the other deficiencies with termination status query in shells. Something like:

  status [-acsfl] [-i <signame>[+]] [-I <signame>[+]]...
  status -p [-acs]

Without argument, status returns true if the previous command succeeds and the same exit status otherwise (mainly a no-op unless ! was used which is ignored).

With:
 - -f -l (implies -a (for all/any)): returns true unless any of the commands in the pipeline did not return true. In which case the status of the first (leftmost) for -f or last (rightmost) for -l is returned instead (if -a is given without -l/-f, -l is implied).
 - -c: returns true if any (with -a) or the last command (without -a) in the last pipeline exited with a coredump.
 - -s: returns true unless any (with -a) or the last command (without -a) in the last pipeline exited with a signal. Otherwise returns the $? corresponding to the signal of that command (the first with -f, the last with -l)
 - -i: when reporting the status, ignore commands that die of a signame signal. If expressed as signame+, also ignore commands that returned with a status corresponding to that signame (-i pipe ignores commands that died of a SIGKILL, -i pipe+ also ignores commands that died of exit(141) (on systems where shells use that code to report a death by SIGPIPE).
 - -I: same as above but only ignores the signal in all but the last pipeline element.

With -p, print status information instead. With -p alone, equivalent to echo "$?" unless ! was used for the last pipeline.

With:
 -a: print the status of all elements of the pipeline, one per line (from the leftmost pipeline element to the rightmost)
 -s: for those commands that died of a signal, print the signal name (pipe/int/kill...) instead of number computed like $?
 -c: for those processes that generated a core, append +core.

Examples:

system("cmd1 | cmd2; status -a") would also check the exit status of cmd1. Similar to:

system("set -o pipefail; cmd1 | cmd2") without side-effects if cmd1 or cmd2 is a function.

system("cmd1 | cmd2; status -aI pipe") same but ignores SIGPIPE death of cmd1

system("cmd1 | cmd2; status -aI pipe+") same but also ignores a *reported* SIGPIPE death.

system("cmd1 | cmd2; status -ai xcpu+ -i alrm+ -I pipe+") ignore xcpu/alrm deaths only report real errors.


cmd1 | cmd2 | cmd3
status -pasc

would print:

pipe
segv+core
0

if cmd2 died of a SIGSEGV and dumped a core and as a result cmd1 died of a SIGPIPE. While cmd3 did an exit(0).

A note about "!":

set -o pipefail
! cmd1 | cmd2

would be written:

cmd1 | cmd2; ! status -a

! cmd2 | cmd2; ! status -a
has the same effect, except in case of "set -e" and cmd2 fails.

What do you think?

(0003904)
jilles (reporter)
2017-12-27 22:54

Given the complication of checking all statuses without a feature like this and the ease with which the shell has all statuses available, I think something like this would be useful.

With the set -o pipefail as implemented in some shells, the application can handle SIGPIPE normally using something like

    (
            cmd1
            r=$?
            if [ "$r" -gt 128 ] && [ "$(kill -l "$r")" = PIPE ]; then
                    exit 0
            else
                    exit "$r"
            fi
    ) | cmd2

Likewise, the dynamic scoping of options can be worked around:

    set -o pipefail
    (set +o pipefail; cmd1) | (set +o pipefail; cmd2)
    r=$?
    set +o pipefail

The status builtin utility proposal above may be a step in the right direction. The shell language being what it is, it will probably end up as something as ad hoc as getopts.

The status builtin reading ephemeral state seems rather error-prone and inflexible. It may be better to set a variable as a side effect of executing a pipeline (like the PIPESTATUS array in some shells) and use the new builtin to interpret it, explicitly passing the value.
(0003905)
stephane (reporter)
2017-12-28 09:43
edited on: 2017-12-29 12:58

Note that the comp.unix.shell FAQ had an entry for that.

It is possible with the current POSIX sh specification to define a helper for that:

https://unix.stackexchange.com/questions/76162/how-do-i-capture-the-return-status-and-use-tee-at-the-same-time-in-korn-shell/76171#76171 [^]

(0004102)
kre (reporter)
2018-09-04 20:36

What has not been considered here is the operation of pipefail
in an asynchronous pipeline.

In particular, at what instant is the setting of the pipefail option
tested.

I see three possibilities (which all amount to the same thing for
foreground pipelines, so it does not matter there)

1) the pipefail option setting when the pipeline is created (and/or perhaps
the setting for each command in the pipeline when it is started). This
allows
      set -o pipefail
      my | pipe | line & P=$!
      set +o pipefail

# and then later

      wait $P

# and here $? is set to the status of the pipeline, using the pipefail option,
even though it is not enabled when the wait is done.

2) the status when the script waits for the status of the pipeline (when the
status is made available to the script). This allows

      my | pipe | line & P=$!

# and later

      set -o pipefail; wait $P; X=$?; set +o pipefail

and X is the status from the pipeline, with the pipefail option set
(regardless of its value when the pipeline was created, or at any
intervening time).

3) The status of the pipefail option is tested as the shell detects that
each process of the pipeline is done (has exited), so in

      set +o pipefail
      (sleep 1; exit 1) | (sleep 5; exit 5) | (sleep 9; exit 0) & P=$?

      sleep 3 sleep 3
      set -o pipefail set -o pipefail
      sleep 4
      set +o pipefail
      sleep 4
      set -o pipefail

      wait $P wait $P

      $? == 0 $? == 5

In the sequence in the left column, pipefail is not set when the
last process exits, so the status of the pipeline is the status of the
rightmost process (0). In the right column, pipefail is enabled then
and so the status of the pipeline is the status of the rightmost
process with non-zero status to exit while the pipefail option was set,
so 5 in this case (the middle of the 3 processes). If that process had
done exit 0 instead of exit 5, the status of the pipeline would be 0, as
the pipefail option was not set when the first process exited, hence its
status is irrelevant.

This 3rd option is, of course, essentially unusable, but is the easiest to
implement - it allows the shell to immediately decide what to do with the
exit status of each command in the pipeline as it exits, it does not need
to retain all the status info until the whole pipeline is finished, which
it would need to do with the 2nd option.

The first option is the most useful I believe, but I also suspect not
implemented anywhere - it allows the shell to collect the status as exch
process in the pipeline exits, and also provides predictable behaviour to
the application. Pity that no-one (that I know of) implements that.

I added pipefail to the NetBSD sh (ash derivative) a while ago, it is in
the NetBSD 8 release shell - that implementation uses scheme 2 above for
dealing with async pipelines (because being different, and implementing (1)
did not seem useful, when no-one else does, and (3), while simple, is
useless.) We have no arrays (and I hope, never will) - there is currently
no way to determine which process in the pipeline produced the status that
is returned when the pipefail option is set. My impression is that most
applications which would want to use it are content to simply discover
"they all worked" and are prepared to write the script in a way to avoid
inadvertent SIGPIPE/EPIPE exit issues (eg: using "sed -e '2,$d'" or
"sed -n -e 1p" rather than "head -n1" or "sed -e 1q"). Alternatively the
script can insert another process whose purpose is to insulate an earlier
process from EPIPE by always reading until EOF, and writing to its stdout,
(just like cat with no args) but ignoring any write errors (or at least,
ignoring EPIPE and also ignoring SIGPIPE ... and always doing exit 0.)

In general I support the pipefail option. I do not think it is required
that everything that could possibly be useful as an adjunct be defined at
the same time - if making the status of the processes in a pipe available
is useful, and arrays are not to be the solution, then something else
should be implemented and made available before anyone worries about
specifying how to do it. Similarly, we do not need to invent ways to
deal with pipes closing - let the applications work on it, and if they
need shell assistance, ask for what they actually need.

But the operation of the option needs to be fully defined (even if that
includes "is unspecified" for some things.)
(0004103)
geoffclare (manager)
2018-09-05 12:36
edited on: 2019-10-03 15:17

Here's an updated version of the wording in the desired action that fixes the incorrect use of "preceding" relating to '!' and the 0/non-zero mixup in the second row of the table, and also addresses the question of when the pipefail setting is obtained that was raised in Note: 0004102 ...

On 2016 edition page 2369 line 75648 section 2.9.2, change:
If the pipeline does not begin with the ! reserved word, the exit status shall be the exit status of the last command specified in the pipeline. Otherwise, the exit status shall be the logical NOT of the exit status of the last command. That is, if the last command returns zero, the exit status shall be 1; if the last command returns greater than zero, the exit status shall be zero.
to:
The exit status of a pipeline shall depend on whether or not the pipefail option (see [xref to set]) is enabled and whether or not the pipeline begins with the ! reserved word, as described in the following table. The pipefail option determines which command in the pipeline the exit status is derived from; the ! reserved word causes the exit status to be the logical NOT of the exit status of that command. The shell shall use the pipefail setting at the time it begins execution of the pipeline, not the setting at the time it sets the exit status of the pipeline. (For example, in <tt>command1 | set -o pipefail</tt> the exit status of <tt>command1</tt> has no effect on the exit status of the pipeline, even if the shell executes<tt>set -o pipefail</tt> in the current shell environment.)
  pipefail Enabled    Begins with !      Exit Status

    no                  no             The exit status of the last (rightmost)
                                       command specified in the pipeline.

    no                  yes            Zero, if the last (rightmost) command
                                       in the pipeline returned a non-zero
                                       exit status; otherwise, 1.

    yes                 no             Zero, if all commands in the pipeline
                                       returned an exit status of 0;
                                       otherwise, the exit status of the
                                       last (rightmost) command specified in
                                       the pipeline that returned a non-zero
                                       exit status.

    yes                 yes            Zero, if any command in the
                                       pipeline returned a non-zero
                                       exit status; otherwise, 1.

On 2016 edition page 2411 line 77180 section set, add after nounset:
pipefail
Derive the exit status of a pipeline from the exit statuses of all of the commands in the pipeline, not just the last (rightmost) command, as described in [xref to 2.9.2].


(0004115)
geoffclare (manager)
2018-09-11 09:42
edited on: 2018-09-11 09:44

Alternative suggestion structured like the NetBSD man page ...

On 2016 edition page 2369 line 75648 section 2.9.2, change:
If the pipeline does not begin with the ! reserved word, the exit status shall be the exit status of the last command specified in the pipeline. Otherwise, the exit status shall be the logical NOT of the exit status of the last command. That is, if the last command returns zero, the exit status shall be 1; if the last command returns greater than zero, the exit status shall be zero.
to:
The exit status of a pipeline is determined via the pipe sequence status as follows:
  • If the pipefail option (see [xref to set]) was enabled when the shell began execution of the pipeline, the pipe sequence status shall be the exit status of the last (rightmost) command in the pipeline that exited with non-zero status, or zero if all commands in the pipeline exited with a status of zero. If the pipefail option was not enabled, the pipe sequence status shall be the exit status of the last (rightmost) command in the pipeline (and the exit statuses of any other commands in the pipeline are not used).

  • If the pipeline begins with the ! reserved word, the exit status of the pipeline shall be the logical NOT of the pipe sequence status as determined above. That is, if the pipe sequence status is zero, the exit status shall be 1; if the pipe sequence status is non-zero, the exit status shall be zero. If the pipeline does not begin with the ! reserved word, the exit status of the pipeline shall be the same as the pipe sequence status.
Note: Since the shell uses the pipefail setting at the time it begins execution of the pipeline, not the setting at the time it sets the exit status of the pipeline, altering pipefail in a command within the pipeline has no effect on the exit status of the pipeline, even if the shell executes the command in the current shell environment.

On 2016 edition page 2411 line 77180 section set, add after nounset:
pipefail
Derive the exit status of a pipeline from the exit statuses of all of the commands in the pipeline, not just the last command, as described in [xref to 2.9.2].


(0004117)
chet_ramey (reporter)
2018-09-11 14:20

I'm curious why the proposed text in note 4103 explicitly chooses kre's option 1 (using the value of pipestatus when the pipeline is started) when, as kre notes in 4102, nobody seems to implement it that way (except ksh93, as Jilles noted later).
(0004118)
geoffclare (manager)
2018-09-11 14:46

Re: Note: 0004117, it's because note 4102 is a complete red herring. Asynchronous commands are lists, and if a pipeline is part of a list its exit status needs to be available in the later commands in the list, e.g.:

command1 | command2 || echo failed &

To make this work the only two possibilities are that either pipefail is checked as the shell begins execution of the pipeline or it is checked as the shell sets the exit status of the pipeline. An application can't tell the difference unless the shell executes one or more of the pipeline commands in the current shell environment (thus allowing pipefail to be changed in that environment during execution of the pipeline). Since ksh93 does that, it makes sense for the standard to specify the ksh93 behaviour.
(0004119)
kre (reporter)
2018-09-11 15:05

Re note 4118...

I'd prefer to say that it is because it is the more sensible choice.
The application knows when it is starting an async pipeline, it does
not necessarily know when one is about to finish in all cases.

Wrt the example - anything run asynchronously is run in a subshell
by definition, so unless the command list alters pipefail inside
itself (as your example in note 4103 did) then the setting of pipefail
at the beginning, and the setting at the end are the same. Aside
from that obscure usage, the only time the difference really matters
is when the option is changed while an async pipeline is running.
(0004120)
chet_ramey (reporter)
2018-09-11 15:56

Re: 4118

That's not the only case. The examples in note 4102 are valid as well. In your example, it doesn't really make a difference because, as you say, existing shells that implement the feature will return the same result. In kre's examples, there will be real differences between implementations.

We can say that the results are undefined if the option is changed while an asynchronous pipeline is running; that would accommodate existing implementations.
(0004121)
geoffclare (manager)
2018-09-11 16:18

Re: Note: 0004120 Okay, I can see that when a pipeline is at the end of an asynchronous list, it would be possible for the time at which "the shell sets the exit status of the pipeline" to be when the wait is done, as per option 2 in note 4102.

However, if done that way it means that for an asynchronous execution of a particular pipeline, where all the commands have the same exit status every time it is run (e.g. false | true), the exit status of the pipeline can differ depending on whether it is obtained as part of the asynchronous list containing the pipeline or is obtained later on with wait. In my view that is just horrible and should not be allowed by the standard.
(0004122)
chet_ramey (reporter)
2018-09-11 18:30

Re: 4121

The situation only arises (that is, the two options produce different results) when the value changes during the asynchronous pipeline's execution. A user could naturally expect that change to have an effect.

Since a shell that implements your preferred option would return consistent results, and a shell that implements option 2 would return (different) consistent results, it comes down to preference.

I think this is a really minor edge case. It's just not the way we usually do things when there are conflicting implementations.
(0004123)
geoffclare (manager)
2018-09-12 08:21

Re: Note: 0004122 I don't see it as minor. To me it is a nasty maintenance issue. Suppose I have a script that does:
set -o pipefail
command1 | command2 || command3 & pid=$!

set +o pipefail
... other stuff that needs pipefail disabled ...

wait $pid

Later on I modify the script and there is new stuff after the wait that needs to know whether the command1 | command2 pipeline failed, so I change it to:
set -o pipefail
command1 | command2 & pid=$!

set +o pipefail
... other stuff that needs pipefail disabled ...

if wait $pid; then
    command3
    ... new stuff ...
fi

If the exit status of the command1 | command2 pipeline now doesn't take into account the exit status of command1, that's a huge gotcha and violates the principle of least surprise.

- Issue History
Date Modified Username Field Change
2013-11-08 16:02 weeks New Issue
2013-11-08 16:02 weeks Status New => Under Review
2013-11-08 16:02 weeks Assigned To => ajosey
2013-11-08 16:02 weeks Name => Nathan Weeks
2013-11-08 16:02 weeks Organization => USDA-ARS
2013-11-08 16:02 weeks Section => 2.9.2
2013-11-08 16:02 weeks Page Number => 0
2013-11-08 16:02 weeks Line Number => 0
2013-11-08 16:06 weeks File Added: pipeline_exit_status.txt
2013-11-08 16:07 weeks Desired Action Updated
2013-11-08 16:15 eblake Note Added: 0001976
2013-11-08 16:50 Don Cragun Interp Status => ---
2013-11-08 16:50 Don Cragun Desired Action Updated
2013-11-08 16:57 Don Cragun Page Number 0 => 2341
2013-11-08 16:57 Don Cragun Line Number 0 => 74464-74467
2013-11-08 16:57 Don Cragun Note Added: 0001977
2013-11-08 16:58 Don Cragun File Deleted: pipeline_exit_status.txt
2013-11-08 21:05 shware_systems Note Added: 0001978
2013-11-12 15:42 weeks Note Added: 0001982
2013-11-12 15:51 eblake Note Added: 0001983
2013-11-12 16:08 shware_systems Note Edited: 0001978
2013-12-11 22:40 weeks Note Added: 0002067
2014-01-16 23:15 shware_systems Note Added: 0002107
2014-05-28 15:47 weeks Note Added: 0002253
2015-05-29 21:14 stephane Note Added: 0002685
2015-05-31 18:27 stephane Note Added: 0002689
2015-05-31 19:27 stephane Note Edited: 0002689
2017-12-27 22:54 jilles Note Added: 0003904
2017-12-28 09:43 stephane Note Added: 0003905
2017-12-29 12:58 stephane Note Edited: 0003905
2018-09-04 20:36 kre Note Added: 0004102
2018-09-05 12:36 geoffclare Note Added: 0004103
2018-09-06 09:07 geoffclare Relationship added related to 0001207
2018-09-11 09:42 geoffclare Note Added: 0004115
2018-09-11 09:44 geoffclare Note Edited: 0004115
2018-09-11 14:20 chet_ramey Note Added: 0004117
2018-09-11 14:46 geoffclare Note Added: 0004118
2018-09-11 15:05 kre Note Added: 0004119
2018-09-11 15:56 chet_ramey Note Added: 0004120
2018-09-11 16:18 geoffclare Note Added: 0004121
2018-09-11 18:30 chet_ramey Note Added: 0004122
2018-09-12 08:21 geoffclare Note Added: 0004123
2019-10-03 15:17 geoffclare Note Edited: 0004103
2019-10-03 15:21 geoffclare Final Accepted Text => Note: 0004103
2019-10-03 15:21 geoffclare Status Under Review => Resolved
2019-10-03 15:21 geoffclare Resolution Open => Accepted As Marked
2019-10-03 15:21 geoffclare Tag Attached: issue8
2020-02-06 10:02 geoffclare Relationship added related to 0000267
2020-06-12 09:58 geoffclare Status Resolved => Applied


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker