Is there some similar option in dash
shell corresponding to pipefail
in bash
?
Or any other way of getting a non-zero status if one of the commands in pipe fail (but not exiting on it which set -e
would).
To make it clearer, here is an example of what I want to achieve:
In a sample debugging makefile, my rule looks like this:
set -o pipefail; gcc -Wall $$f.c -o $$f 2>&1 | tee err; if [ $$? -ne 0 ]; then vim -o $$f.c err; ./$$f; fi;
Basically it runs opens the error file and source file on error and runs the programs when there is no error. Saves me some typing. Above snippet works well on bash
but my newer Ubunty system uses dash
which doesn't seem to support pipefail
option.
I basically want a FAILURE status if the first part of the below group of commands fail:
gcc -Wall $$f.c -o $$f 2>&1 | tee err
so that I can use that for the if
statement.
Are there any alternate ways of achieving it?
Thanks!
pipefail. If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands in the pipeline exit successfully. This option is disabled by default.
set -o pipefail causes a pipeline (for example, curl -s https://sipb.mit.edu/ | grep foo ) to produce a failure return code if any command errors. Normally, pipelines only return a failure if the last command errors. In combination with set -e , this will make your script exit if any command in a pipeline errors.
Dash (Debian Almquist shell) is a modern POSIX-compliant implementation of /bin/sh (sh, Bourne shell). Dash is not Bash compatible, but Bash tries to be mostly compatible with POSIX, and thus Dash. Dash shines in: Speed of execution. Roughly 4x times faster than Bash and others.
From man bash : -s If the -s option is present, or if no arguments remain after option processing, then commands are read from the standard input. This option allows the positional parameters to be set when invoking an interactive shell.
In this case, it sets the pipefail option. If set, causes the pipeline to return the exit status of the last (rightmost) command to exit with a non-zero status. It returns zero if all commands in the pipeline exit successfully.
However, dash doesn't have the pipefail option, which is why you're getting the error.
The Linux set and pipefail commands dictate what happens when a failure occurs in a Bash script. There’s more to think about than should it stop or should it carry on. Sorry, the video player failed to load. (Error Code: 100013) Bash shell scripts are great. They’re quick to write and they don’t need compiling.
If you’re using the shell module with Ansible and piping the output to another command, it might be a good idea to set pipefail. This way, if the first command fails, the whole task will fail. For example, let’s say we’re running this silly task to look for /tmp directory and then trim the string “ tmp ” from the result.
I ran into this same issue and the bash options of set -o pipefail
and ${PIPESTATUS[0]}
both failed in the dash shell (/bin/sh) on the docker image I'm using. I'd rather not modify the image or install another package, but the good news is that using a named pipe worked perfectly for me =)
mkfifo named_pipe tee err < named_pipe & gcc -Wall $$f.c -o $$f > named_pipe 2>&1 echo $?
See this answer for where I found the info: https://stackoverflow.com/a/1221844/431296
The Q.'s sample problem requires:
I basically want a FAILURE status if the first part of the ... group of commands fail:
Install moreutils, and try the mispipe
util, which returns the exit status of the first command in a pipe:
sudo apt install moreutils
Then:
if mispipe "gcc -Wall $$f.c -o $$f 2>&1" "tee err" ; then \ ./$$f else vim -o $$f.c err fi
While 'mispipe' does the job here, it is not an exact duplicate of the bash
shell's pipefail
; from man mispipe
:
Note that some shells, notably bash, do offer a pipefail option, however, that option does not behave the same since it makes a failure of any command in the pipeline be returned, not just the exit status of the first.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With