I have two processes
bar, connected with a pipe:
$ foo | bar
bar always exits 0; I'm interested in the exit code of
foo. Is there any way to get at it?
If you are using
If you are using
To combine them within a function in a manner that doesn't lose the values:
Run the above in
There are 3 common ways of doing this:
The first way is to set the
Bash also has an array variable called
You can use the 3rd command example to get the specific value in the pipeline that you need.
This is the most unwieldy of the solutions. Run each command separately and capture the status
While not exactly what you asked, you could use
so that your pipes return the last non zero return.
might be a bit less coding
What I do when possible is to feed the exit code from
Or if I know that the output from
This can always be done if there's some way of getting
If you need to capture the output from
And, of course, there's the simple option of using a temporary file to store the status. Simple, but not that simple in production:
This solution works without using bash specific features or temporary files. Bonus: in the end the exit status is actually the exit status and not some string in a file.
you want the exit status from
Here is my solution:
Note: the child process inherits the open file descriptors from the parent. That means
If you worry that your
Step by step explanation of the construct:
From bottom up:
Starting from the pipeline:
Here is a general solution using only POSIX shell and no temporary files:
Note the quotes around
So I wanted to contribute an answer like lesmana's, but I think mine is perhaps a little simpler and slightly more advantageous pure-Bourne-shell solution:
I think this is best explained from the inside out – command1 will execute and print its regular output on stdout (file descriptor 1), then once it's done, printf will execute and print command1's exit code on its stdout, but that stdout is redirected to file descriptor 3.
While command1 is running, its stdout is being piped to command2 (printf's output never makes it to command2 because we send it to file descriptor 3 instead of 1, which is what the pipe reads). Then we redirect command2's output to file descriptor 4, so that it also stays out of file descriptor 1 – because we want file descriptor 1 free for a little bit later, because we will bring the printf output on file descriptor 3 back down into file descriptor 1 – because that's what the command substitution (the backticks), will capture and that's what will get placed into the variable.
The final bit of magic is that first
You can look at it in a less technical and more playful way, as if the outputs of the commands are leapfrogging each other: command1 pipes to command2, then the printf's output jumps over command 2 so that command2 doesn't catch it, and then command 2's output jumps over and out of the command substitution just as printf lands just in time to get captured by the substitution so that it ends up in the variable, and command2's output goes on its merry way being written to the standard output, just as in a normal pipe.
Also, as I understand it,
Per the caveats lesmana mentions, it's possible that command1 will at some point end up using file descriptors 3 or 4, so to be more robust, you would do:
Note that I use compound commands in my example, but subshells (using
Commands inherit file descriptors from the process that launches them, so the entire second line will inherit file descriptor four, and the compound command followed by
I'm not sure how often things use file descriptor three and four directly – I think most of the time programs use syscalls that return not-used-at-the-moment file descriptors, but sometimes code writes to file descriptor 3 directly, I guess (I could imagine a program checking a file descriptor to see if it's open, and using it if it is, or behaving differently accordingly if it's not). So the latter is probably best to keep in mind and use for general-purpose cases.
---OUTDATED CONTENT BELOW THIS LINE---
For historical reasons, here is my original, not-portable-to-all-shells answer:
[EDIT] My bad, this does not work with bash because bash needs extra coddling when fiddling with file descriptors, I will update this as soon as I can. [/EDIT]
So I wanted to contribute an answer like lesmana's, but near as I can tell, mine is the simplest and most light-weight of the pure-Bourne-shell solutions:
Per the caveats lesmana mentions, it's possible that command1 will at some point end up using file descriptor 3, so to be more robust, you would do:
The subshell around command1 will inherit file descriptor 3 from the main shell, but that
If you have the moreutils package installed you can use the mispipe utility which does exactly what you asked.
lesmana's solution above can also be done without the overhead of starting nested subprocesses by using
I've checked this construct with dash version 0.5.5 and bash versions 3.2.25 and 4.2.42, so even if some shells don't support
With a bit of precaution, this should work:
The following 'if' block will run only if 'command' succeeded:
Specifically speaking, you can run something like this:
Which will run
Notice that pipes automatically clean themselves up; with the redirection you'll have to be carefull to remove "$haconf_out" when done.
Not as elegant as
This is portable, i.e. works with any POSIX compliant shell, doesn't require the current directory to be writable and allows multiple scripts using the same trick to run simultaneously.
Edit: here is a stronger version following Gilles' comments:
Edit2: and here is a slightly lighter variant following dubiousjim comment:
Following is meant as an addon to the answer of @Patrik, in case you are not able to use one of the common solutions.
This answer assumes following:
This can be used as a plugin replacement for a single command and only needs following:
This script has a bug in case
EDIT: This answer is wrong, but interesting, so I'll leave it for future reference.