Reputation: 920
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
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
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