tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: RFC: Change to the way sh -x works ?

    Date:        Sun, 12 Nov 2017 15:34:55 -0500
    From: (Christos Zoulas)
    Message-ID:  <>

  | | Two different "enable trace" options would be a mess, and wouldn't work
  | | all that well (what do we do if both are enabled?)
  | Error out, ignore the second?

No, I don't think so, either would be ugly -- and just ignoring changes
to -x because -X happens to be set has the potential to break things more
badly then the previous proposal ever had, and generating an error would
make -X impossible to use with some scripts, for no good reason.

I have a slightly different idea to suggest instead (this one is not yet
fully implemented, it is more complex than the previous, so no demo,
but I think it will be easy enough to understand how it should work.)

First, "set -x" stays as it has been in the past, and enables/disables
tracing, and if nothing else is done, follows stderr around as it is
changed (each trace message will go to whatever happens to be stderr at
the time it is generated).   Anything currently using -x, will see no

 [ An aside; just to clarify something which is not changing - tracing
   happens before any redirects on the command line, so (assuming -x is set)
   "echo foo 2>/dev/null" does not send the trace output for the echo command
   to /dev/null, but "{ echo foo ;} >/dev/null does.  That does not make it
   silent wrt tracing however, as the { } compound is still traced, at
   least in netbsd-8/current sh. ]

To this a new -X (aka Xtrace) option is added - think of it as a "super x",
or to use 1940's/1950's British terminology, for at least some classes
of Brits of the era, "capital x"...   (I think ... that's a bit before my
time, and not my country, and not quite the way the idiom would have been

Any change to -X is also (immediately after) performed on -x as well (the
sequencing is important).   But in addition to turning on command tracing
(when enabled by "set -X" or -X on the command line), this option also locks
the trace output to go to whatever stderr is at the time the X option is
turned on.   This time the intent will be that any time "set -X" is done,
stderr at the time will become the trace destination - since nothing is
currently using this option (as it does not yet exist) there is no need
to deal with unintentional manipulation in existing scripts, which was the
motivation for the "only when going from off to on" that was in the previous
proposal, and which was a bit ugly, and which had a special case exception I
never bothered to mention... and now never need to.)

Existing scripts that want to manipulate (turn on/off) tracing, will work
just fine with this, $- will show the 'x' option set whenever tracing
is enabled, and clear when it isn't, and set -x or set +x can be used to
enable/disable tracing regardless of whether -X is set or not.   $- will
also show the X option if that is set, but existing scripts will have no
idea what that means, and should just leave it alone.

What won't work is saving options with "set +o" and restoring them later -
the options will be saved/restored just fine, but there is no way to work
out where stderr is being sent (ie: the path name) in order to get that
back again later (consider "sh -X 2>/tmp/trace-file script" where "script"
then  uses "set +o" to save the options, and either it, or even some other
script being run by a different instance of sh, later executes the output
from the "set +o" to restore the options - all sh knows is "stderr is
directed to some file somewhere..." it cannot supply a file name.)
Of course, the previous proposal had that problem as well.

When Xtrace is disabled ("set +X"), tracing is disabled (this does "set +x"
as a side effect) and then if later enabled again using "set -x" the trace
output will go back to being to whatever is current stderr.  The idea is
that users who want the new style, can just use -X/+X as a direct replacement
for -x/+x (unless they want to do something fancy, in which case making use
of both the X and x options could be required.)

Does this seem more reasonable (or safer) than the previous suggestion ?


ps: I did not think to mention the last time, but in both that proposal, and
this one, if a function contains "local -" (ie: option changes are local
to the function) then when the function returns, any changes to -x (or -X)
that occurred during the function (after that local command, of course),
including any changes to where the tracing gets sent, will be undone (tracing
will go back to where it was being sent before the function changed it, if
it did -- "local -" is more often used in functions that change "-f" or "-e"
and similar, than those that are playing with -x.)

Home | Main Index | Thread Index | Old Index