capture piped command status in ksh

The explanations I found are not so clear so I will write my own ... Consider the following script fail.sh:
echo "this is a failing script"
echo "this will fail after this line"
return 1
Now here is the problem, suppose this script needs to be called in the following form :
fail.sh | tee fail.log 
What happens if you check the return code ( $? ) of this command is that you will get a nice 0. The return code only gives you the return of the last command which was executed by the shell. In our example that would be tee and it worked fine, but we want to capture the failure in the middle ... The following is by no means original, I built it from various sources on the net:
exec 3>&1
status=`((fail.sh 2>&1 ; echo $? >&4)| tee fail.log >&3) 4>&1`
echo $status
Alright, so I assume you (like me) know that 1 is the stdout file descriptor and that 2 is the stderr file descriptor. But what the hell are 3 and 4 ?!
  • 3 is a copy of the stdout file descriptor.This copy is done with the initial exec command.Throughout the execution of the line, anything directed to it will get on the stdout of the wrapping script. Thus the tee output is redirected to it so we see the output of fail.sh on the terminal.
  • 4 is a file descriptor to a new buffer which receives the value of the exit code and is merged in stdout at the end of the command. Since the line is executed in backticks the stdout is stored in the status variable.
  • The 2>&1 is the classic merge of stderr in stdout for the fail command. this is useless here as our script doesn't output anything on stderr but it can come in handy with other scripts.


Starting an Eclipse headless build from ant

The following snippet will allow you to start an headless eclipse instance and make it start an ant script:
<java classname="org.eclipse.core.launcher.Main" fork="true" failonerror="true" maxmemory="1024m" logError="true" resultproperty="eclipse.run.result">                            
  <arg value="-application"/>
  <arg value="com.ibm.etools.j2ee.ant.RunAnt"/>
  <arg value="-buildfile" />
  <arg value="${build.dir}\masterBuild.xml" />       
  <arg value="-data"/>
  <arg value="${workspace}"/>             
    <pathelement location="${wid.home}/eclipse/startup.jar"/>
  <jvmarg value="-Dlog.dir=${automation.home}/dailybuilds/output/logs"/>
I use this to run the Webspehre integration developper build process from cruise control in a cross platform way.