Date: Thu, 13 Jun 2024 11:51:13 -0400 From: "Dale R. Worley" <wor...@alum.mit.edu> Message-ID: <87jzisx2mm....@hobgoblin.ariadne.com>
| For instance, how should this be logged? | | $ { echo foo ; echo bar ; } >/dev/null In the NetBSD shell: [jacaranda]{2}$ { echo foo ; echo bar ; } >/dev/null + using redirections: >/dev/null do { + echo foo + echo bar + } done The redirections need to be listed first, as by the time we get to the '}' (at run time) there's no longer any record of what they were (just, in this case, which fd needs to be restored to be stdout). | (Interestingly, I just discovered that "local" environment variable | settings that apply to only one command are logged by set -x: | | $ FOO=BAR echo baz Again, they don't have to be (the bash way means no difference between "FOO=BAR; echo baz" and "FOO=bar echo baz"): [jacaranda]{2}$ FOO=BAR echo baz + FOO=BAR echo baz baz [jacaranda]{2}$ FOO=bar; echo baz + FOO=bar + echo baz baz And just for completeness: [jacaranda]{2}$ cat </dev/null >/tmp/foo 3>/tmp/bar + cat </dev/null >/tmp/foo 3>/tmp/bar No remembering of input lines, the last of those could be input instead as: [jacaranda]{2}$ </dev/null >/tmp/foo cat 3>/tmp/bar + cat </dev/null >/tmp/foo 3>/tmp/bar The command is output first, then the redirections in the order they're executed. Of course, variables (etc) are expanded: [jacaranda]{2}$ X=/dev/null Y=/tmp/foobar + X=/dev/null Y=/tmp/foobar [jacaranda]{2}$ cat $X > $Y + cat /dev/null >/tmp/foobar It is possible to do all this sensibly, it does not need to be the bash way, (the actual output from the first of the examples above could be altered, some people like it, some don't....) it all just depends upon how much work the shell is willing to do (or more accurately, as this is negligible execution time, how much work the shell author is willing to do). Unfortunately for many of you, you need to either do a whole lot of (mostly tedious) work, or run NetBSD to get the NetBSD shell - all the sources are available, but it takes some effort to build it elsewhere. kre ps: we also have set -X, which locks the output file descriptor for output from set -x to be that which exists (as stderr) when set -X was executed, ignoring any redirections of stderr that might apply to the command being executed. And yes, that means "set -X 2>/tmp/trace" causes all (further) output from set -x to go to that file, but more simply: [jacaranda]{2}$ ( cat /no/such/file ) 2>/dev/null + using redirections: 2>/dev/null do subshell ( + ) done subshell [jacaranda]{2}$ set -X + set -X [jacaranda]{2}$ ( cat /no/such/file ) 2>/dev/null + using redirections: 2>/dev/null do subshell ( + cat /no/such/file + ) done subshell The error message from cat about failing to open the file was sent to /dev/null in both cases, the tracing output from inside the subshell also in the first. With -X (which locked the trace output to the current stderr at the time it was executed) tracing output from the command in the subshell still appears on the parent shell's stderr. Set +X disables that again, naturally, or another set -X can alter where future tracing goes. (And for completeness, while it need not have been this way, set -X performs an implicit set -x, and set +X does an implicit set +x so that it is not needed to do "set -Xx" or anything, set -x/set +x continue to work as normal, and don't alter what the -X option is doing, or not doing.)