Search code examples
bashexecevalfile-descriptorexit-code

In Bash, how to capture exit status code from a command nested within a complex statement


I'm relatively new to working with bash. I've inherited this bit of code to run a command via SLURM on an HPC system:

CMD="srun -srunParam1 ... -srunParamN ./scriptToRun.sh -scriptParam1"
exec 5>&1
results=$(eval "${CMD}" | tee - >&5)) 

That all works just fine.

But, I need to capture the exit status of just eval "${CMD}", and don't know how to do it.

Initially, I put exitStatus=$? after the results=... command; but, I believe that's catching the status of assigning a value to the results variable, and not of eval ${CMD}

The script goes on to process the output that is in $results. I don't really understand why the file descriptor has been opened here (or, how to properly use file descriptors). But, I'll save that for further research/a separate question.

EDIT: I commented out the bits with the file descriptor, and observed that the script still works, but $results does not contain the output from running $CMD - it only contains the post-processing of $CMD.


Solution

  • Bash has PIPESTATUS:

    results=$(eval "${CMD}" | tee - >&5; exit ${PIPESTATUS[0]}) 
    exitStatus=$?
    

    Note that in the code above we are examining the exit status of a command that was run inside a subshell ($(...)); it would not work to access PIPESTATUS in the parent.