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.)




Reply via email to