export VAR=$(cmd1 | cmd2)
does not count as a pipefail when cmd1 or cmd2 fail but VAR=$(cmd1 | cmd2)
does, so the "correct" way to set an environment variable from a pipeline's output is actually VAR=$(cmd1 | cmd2)
export VARAnd that is fine; but sometimes you want to treat a pipeline as a "single command" and then you can use pipefail to abort the pipeline on error. Then you can handle the error at the granularity of the entire pipeline without caring which part failed.
Lastly, I am confused as to the "silent" failures; maybe you are thinking of combining this with `set -e`? Then yes, that is bad and I recommend against the combination; but then again, I and most advanced scripters recommend against shotgunning `set -e` in the first place. Use it in specific portions of the script when appropriate, and use proper error handling otherwise.
set -e
command
command [fails]
command
Whether the above reports error or not depends on the command; when you have a pipeline failing in the above way, it is even sneakier: set -e
command
command | command | command [fails]
command
You are reliant on all commands in the pipeline being verbose about failure to signal error.None of the above is advisable. The advisable code is
error_handler() { proper error handling; }
command || error_handler "parameter"
command || error_handler "parameter"
{ command | command | command; } || error_handler "parameter"
{
set -e
exceptional section that needs to be bailed out
set +e
}
command || error_handler "parameter""Pipefail is useful and very hard to emulate on pure POSIX; you need to create named fifos, break the pipeline into individual redirections and check for error on each line.
And that is fine; but sometimes you want to treat a pipeline as a "single command" and then you can use pipefail to abort the pipeline on error. Then you can handle the error at the granularity of the entire pipeline without caring which part failed."
By the way, I never script in Bash; I only script in POSIX primitives using dash as my executable.