GregH
GregH

Reputation: 12868

Why is "set -x" (xtrace) output not subject to redirections unless wrapped in braces?

I am enabling echoing of commands in a bash script using "set -x". When I turn off echoing, I am issuing "set +x" but I don't want that command echo'd. To do this, I issue the command:

{ set +x; } 2>/dev/null

This works fine. However, I'm not completely understanding why this works and the following does not:

set +x 2>/dev/null 

Obviously the echoing of the command doesn't go to stderr, but I'm not really understanding why the command with the semicolon in the curly braces works.

Upvotes: 5

Views: 2215

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295472

The reason you need to use braces is that xtrace logging (the + set +x line you're trying to suppress) is not output from the command set +x itself (a command which, on its own, writes nothing to either stderr or stdout). Instead, it's output from the shell invoking set +x.

When you run set +x 2>/dev/null, that redirects stderr to /dev/null only for the execution of set +x itself. It does not redirect things the shell does while setting up to run that command, which includes printing trace logs.

By contrast, when you run { set +x; } 2>/dev/null, that does the redirection before running the entire block of code, which includes by nature pre-command setup for each command within that block. Thus, the setup for the command is run in the redirected environment as well.

You wouldn't want it to be otherwise -- what use would set -x be if someprogram 2>/dev/null didn't log that it had invoked someprogram at all?


Incidentally, this is very similar to why the shell-builtin time command's output is not subject to redirection unless wrapped in a larger context; for more on that, see BashFAQ #32.

Upvotes: 10

Related Questions