Newsgroups: comp.unix.shell Subject: Re: Propagating Exit Status in a Pipeline References: <[email protected]> <01bc9480$11d92720$88be2399@hp-customer> From: [email protected] Lines: 104 X-Newsreader: Gnus v5.3/Emacs 19.34 Date: 20 Jul 1997 09:40:01 -0700 Message-ID: --text follows this line-- if you want the exit status of cmd1, in cmd1 |cmd2 |cmd3, try something like the following (untested): exec 5>&1 # store original stdout result=` ( ( cmd1; echo $? 1>&3 # echo the exit status of cmd1 into descriptor # 3, the stdout of the backticks, so it gets # stored into result ) | cmd2 | cmd3 ) 3>&1 # copy the stdout of the backticks to descriptor 3 (for # use by the echo command) 1>&5 # make the stdout of cmd3 be the original stdout ` exec 5>&- $result now contains the exit status of cmd1. to understand how this works, you have to be aware that the shell forks from right to left, interpreting the redirections from left to right inside each command. so, what happens is: the global stdout is saved to desc 5. the stdout being assigned to result (originally destined to be the stdout of cmd3) is saved to desc 3. the stdout of cmd3 is redirected to the global stdout (so you'll see it, or it'll end up in whatever file you redirected the script into, or whatever). then cmd2 and cmd are forked, and all the commands begin to run more or less simultaniously. after cmd1 finishes executing, the echo command's stdout is redirected into desc 3, so whatever it prints will be assigned to result. $? contains the exit status of cmd1, so it is what is prints is the exit status of cmd1. if you want to assign the output of the pipeline to a variable, and get the exit status of something other than the last command, a few named pipes could come in handy... TMPFIFO1=/tmp/fifo1.$$ TMPFIFO2=/tmp/fifo2.$$ mknod $TMPFIFO1 p mknod $TMPFIFO2 p (cmd1; result=$?; exec 1>&-; echo $result 1> $TMPFIFO2) | cmd2 | cmd3 > $TMPFIFO1 & output=`cat $TMPFIFO1` result=`cat $TMPFIFO2` rm -f $TMPFIFO1 $TMPFIFO2 the theory here is that by closing the stdout of the subshell cmd1 is running in, cmd2 will get an EOF, and eventually cmd2 and cmd3 will terminate, causing the 'cat $TMPFIFO1' to terminate (so we don't end up in deadlock). meanwhile, the 'echo $result 1> $TMPFIFO2' will have blocked, waiting for the 'cat $TMPFIFO2' the 'result' variable in the cmd1 subshell is separate (since it's in a separate shell). it is required so the echo echoes the result of cmd1 and not the result of 'exec 1>&-', which will pretty much always be true (ain't shell scripting grand? where else is 0 true and 1 false?). also, by using more fifos, you could use this technique to capture the exit status of more than one command in the same pipeline. as for getting the exit status of an rsh command, if you don't need any output, just put an 'echo $?' at the end of it, and save the output. if you *do* need output, as long as it's text, and all the lines end in a newline, you could just make the last line be the exit status... something like: OUTPUTFILE=/some/file/name result=`rsh somehost 'somecommand; echo $?' | ( IFS="" # needed to maintain leading/trailing tabs in lines : > $OUTPUTFILE read oldline while read line do echo "$oldline" >> $OUTPUTFILE oldline="$line" done echo "$oldline" ) ` best of luck, andru