I’m trying to debug a shell script that uses dialog(1), which has the unfortunate habit of overwriting the debug output I wanted to see.
After quite some time banging my head against the wall, I grabbed the source to dialog to look at their examples.
Their examples follow a pattern I have NOT been following; I’m now looking at this trying to understand WTF it does:
1 exec 3>&1
2 returntext=`$DIALOG --title "RANGE BOX" --rangebox "Please set the volume..." 0 60 0 123 5 2>&1 1>&3`
3 returncode=$?
4 exec 3>&-
so… ok.
Line 1 duplicates FD 1 (stdout) into FD 3. That’s usually so we can mess with FD 1 later on and still have a handle to stdout. Good so far.
Line 2 runs /usr/bin/dialog in a subshell, the options to dialog(1) are irrelevant here. I’m looking at the redirects.
“2>&1” duplicates FD 1 into FD 2, effectively throwing away the handle to the inherited /dev/stderr and forcing stderr output onto stdout. That’s a good thing because dialog(1) reports its results onto stderr by default to avoid messing with curses(3) output.
“1>&3” however, throws away stdout (FD 1), replacing it with FD 3 which is… already a copy of FD 1 ???
Line 3 is obvious.
Line 4 closes FD 3. Not sure that we need to bother, but OK, cleaning up behind ourselves is usually a good thing.
I get the need for swapping stdin/stderr, as dialog(1) – well, really curses(3) - uses stdout to paint the screen, so dialog(1) spits its results out on stderr to avoid conflicting. If we’re in a subshell trying to capture that output, we need to grab it just as dialog(1) exits – and $() assignment only captures stdout.
But what’s the point of having FD 3 in this setup, if all we do is assign it to stdin inside the subshell and then forget about it?
Can anyone see what I’m missing here?
-Adam