If you really do not want the second command to continue until the first, as you know, is successful, you will probably have to use temporary files. Simple version:
tmp=${TMPDIR:-/tmp}/mine.$$ if ./a > $tmp.1 then if ./b <$tmp.1 >$tmp.2 then if ./c <$tmp.2 then : OK else echo "./c failed" 1>&2 fi else echo "./b failed" 1>&2 fi else echo "./a failed" 1>&2 fi rm -f $tmp.[12]
Redirection '1> & 2' can also be abbreviated '> & 2'; however, the old version of the MKS shell incorrectly redirected the error without the previous â1â, so I used this unique notation for reliability for many years.
This is a file leak if you interrupt something. Bomber (more or less) shell programming uses:
tmp=${TMPDIR:-/tmp}/mine.$$ trap 'rm -f $tmp.[12]; exit 1' 0 1 2 3 13 15 ...if statement as before... rm -f $tmp.[12] trap 0 1 2 3 13 15
The first line of the trap says: "Run the commands" rm -f $tmp.[12]; exit 1 rm -f $tmp.[12]; exit 1 "when any of the signals 1 SIGHUP, 2 SIGINT, 3 SIGQUIT, 13 SIGPIPE or 15 SIGTERM or 0 occurs (when the shell exits for some reason) If you are writing a shell script, the last trap only needs to remove the trap to 0, which is a trap for exiting the shell (you can leave other signals in place, as the process is about to end).
In the source pipeline for 'c' it is possible to read data from 'b' before the completion of 'a' - this is usually desirable (for example, for several cores to work). If "b" is the "sort" phase, this will not apply - "b" must see all of its data before it can generate any of its output.
If you want to detect which commands are not executing, you can use:
(./a || echo "./a exited with $?" 1>&2) | (./b || echo "./b exited with $?" 1>&2) | (./c || echo "./c exited with $?" 1>&2)
It is simple and symmetrical - it is trivial to extend to a 4-part or N-part conveyor.
Simple experiments with 'set -e' did not help.
Jonathan Leffler Oct 11 '09 at 15:40 2009-10-11 15:40
source share