I want to capture the exit status of a command that takes place somewhere in a pipeline before the last position. For example, if the pipeline is something like
command_1 ... | command_2 ... | command_3 ... | ... | command_n
...I would like to know how to capture the exit status of command_1
, or of command_2
, or of command_3
, etc. (Capturing the exit status of command_n
is trivial, of course.)
Also, in case it matters, this pipeline is occurring inside a zsh shell function.
I tried to capture the exit status of command_1
with something like
function_with_pipeline () {
local command_1_status=-999999 # sentinel value
{ command_1 ...; command_1_status=$? } | command_2 ... | ... | command_n
...
}
...but after running the pipeline, the value of the command_1_status
variable was still the sentinel value.
FWIW, here's a working example, where the pipeline has only two commands:
foo ... | grep ...
foo
is a function defined for the sake of this example, like so:
foo () {
(( $1 & 1 )) && echo "a non-neglible message"
(( $1 & 2 )) && echo "a negligible message"
(( $1 & 4 )) && echo "error message" >&2
return $(( ( $1 & 4 ) >> 2 ))
}
The goal is to capture the exit status of the call to foo
in the pipeline.
The function function_with_pipeline
implements the (ultimately ineffective) strategy I described above to do this:
function_with_pipeline () {
local foo_status=-999999 # sentinel value
{ foo $1; foo_status=$? } | grep -v "a negligible message"
printf '%d\ndesired: %d; actual: %d\n\n' $1 $(( ( $1 & 4 ) >> 2 )) $foo_status
}
The loop below exercises the function_with_pipeline
function. The output shows that the value of the local variable foo_status
ends up no different from how it started.
for i in $(seq 0 7)
do
function_with_pipeline $i
done
# 0
# desired: 0; actual: -999999
#
# a non-neglible message
# 1
# desired: 0; actual: -999999
#
# 2
# desired: 0; actual: -999999
#
# a non-neglible message
# 3
# desired: 0; actual: -999999
#
# error message
# 4
# desired: 1; actual: -999999
#
# error message
# a non-neglible message
# 5
# desired: 1; actual: -999999
#
# error message
# 6
# desired: 1; actual: -999999
#
# error message
# a non-neglible message
# 7
# desired: 1; actual: -999999
#
I get the same results if I omit the local
declaration in the definition of foo_status
.