Jacek Trociński
Jacek Trociński

Reputation: 920

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}"

Upvotes: 2

Views: 440

Answers (2)

chepner
chepner

Reputation: 532093

If you are willing to use a named pipe, you can dispense with all the file-descriptor wrangling:

mkfifo p
tee -a somefile.txt < p &
. somescript.sh > p
rc=$?

Here, we run tee in the background, letting it read its input from a named pipe p. Once that job is started, we source the script and redirect its output to the named pipe. Once the script completes, you can save its exit status to rc using an ordinary assignment statement. This will also close the shells end of the pipe, which will cause the other end to close as well and allow tee to exit.

Upvotes: 1

cxw
cxw

Reputation: 17051

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.

Upvotes: 2

Related Questions