Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I need to execute a number of piped shell commands from a non-BASH script (namely PHP script) like these:

command1 | command2 | command3

so that, if command1 fails with a non-zero exit code, each other command fails too. So far, what I've come up with is:

set -o pipefail && command1 | command2 | command3

But even though it runs fine from the terminal, it produces this if executed from the script:

sh: 1: set: Illegal option -o pipefail

share|improve this question

migrated from Nov 24 '12 at 18:12

This question came from our site for professional and enthusiast programmers.

It appears that /bin/sh doesn't like set -o pipefail. Is it actually bash in disguise, or is it a different shell? When bash is run as /bin/sh, does it accept set -o pipefail? – Jonathan Leffler Nov 24 '12 at 17:24
@JonathanLeffler When I run /bin/sh set -o pipefail it says /bin/sh: 0: Can't open set (same thing with sudo). Hope I tested it right. The system is Ubuntu 12. – Desmond Hume Nov 24 '12 at 17:36
You'd need to try /bin/sh -c "set -o pipefail"; as it was, the shell was trying to execute a script in the current directory called set and it didn't find it. – Jonathan Leffler Nov 24 '12 at 19:29
@JonathanLeffler /bin/sh -c "set -o pipefail" isn't working, however bash -c "set -o pipefail" does. – Desmond Hume Nov 24 '12 at 19:46
So, your problem is that the script is run by /bin/sh which doesn't recognize set -o pipefail. Consequently, you'll need to ensure that the script is run by /bin/bash instead of /bin/sh. Or, if you're confident, brave — and probably foolhardy — change /bin/sh to be a link to, or copy of, /bin/bash instead of whichever shell it currently is linked to or a copy of. If you're sure that /bin/sh is bash, then you're using behaviour which bash doesn't expose when run as /bin/sh; use bash as bash. – Jonathan Leffler Nov 24 '12 at 19:50
up vote 6 down vote accepted

From the Bash command line you would need to invoke a subshell to avoid pipefail being set afterwards:

$ (set -o pipefail && command1 | command2 | command3)

This would limit the effect of the pipefail option to the subshell create by the parentheses (...).

A real example:

$ (set -o pipefail && false | true) && echo pipefail inactive || echo pipefail active
pipefail active

If you use an explicit shell call with the -c option you do not need a subshell, either with bash or with an sh alias to bash:

$ bash -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active
$ sh -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active

Since your sh does not accept the pipefail option, I would have to assume that it is either some older or modified version of bash - or that it is actually some other shell completely.

share|improve this answer
Is $ in the first piece a part of the command is it just a shell prompt? Tried both ways, didn't really work. The bash -c way always works, not too elegant tho.. – Desmond Hume Nov 24 '12 at 19:36

You can use $(command1) combined with $? :

a=$(echo "a")
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

Prints "abc"

a=$(ls unexitingDir)
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

Prints "".

"[ $? -eq 0 ] &&" means that the following command is executed only if the previous one succed.

That dosen't answer your question but it's a solution to your problem.

share|improve this answer
Does it mean that I would always need to store the output of each of the commands into a variable? – Desmond Hume Nov 24 '12 at 15:44
Always I don't know but with my solution yes you will (if you need it for your next command). Unless you can just write command1 && command2 && command3 – Christian Glacet Nov 24 '12 at 18:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .