Search code examples
kshfile-descriptor

output file descriptor redirection


I need to be able to redirect output to a file and also check the return code of a script in KSH (can't use pipestatus or pipefail), I have found a solution but I'm not sure what the significance of file discriptor 4 is, can someone explain please?

{
rc=$(
{
  {
    . somescript.sh 2>&1
    echo "$?" >&3
  } | tee -a somefile.txt
} 3>&1 >&4 4>&-
)
} 4>&1

echo "${rc}"

Solution

  • rc=$(...) means that the return code will be whatever is printed on file descriptor (fd) 1 by the code within the (...). So, somehow, what somescript.sh outputs has to be moved off fd 1 and then brought back later. The echo line outputs somescript.sh's return code to fd 3. Then, 3>&1 sends the saved return code to fd 1, where $(...) expects it. However, this means the old fd 1 (from {somescript 2>&1 } | tee) doesn't have anywhere to go. So the old fd 1 is redirected to fd 4 with >&4 (and the input side is closed with 4>&- since it won't be used). Then, once the $(...) is over, the 4>&1 at the end puts the output of the somescript|tee back onto fd 1 where other programs expect it to be.

    Whew!

    Without the >&4, the output of somescript.sh and the output of echo "$?" would be mixed on fd 1 because of the 3>&1. So fd 4 is a holding pen for the actual output of somescript.sh during the time that fd 1 is being used to carry the return code.