Reputation: 1272
I have a bash script with output that I'm trying to debug by running bash with -x
. I'd also like the output to be redirected to stdout instead of stderr (because the logging framework we use treats all stderr content as high-priority errors).
However, command substitutions in my code are failing because the lines logged by set -x
are getting mixed in with the actual intended output, as shown in the below log.
How can I avoid this bug while directing set -x
logs to stdout?
Example:
root@ee0d2037fdca:/# $(echo "ls")
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@ee0d2037fdca:/# set -x
root@ee0d2037fdca:/# export BASH_XTRACEFD=1
+ export BASH_XTRACEFD=1
+ BASH_XTRACEFD=1
root@ee0d2037fdca:/# $(echo "ls")
+ ++ echo ls ls
bash: ++: command not found
root@ee0d2037fdca:/#
Upvotes: 0
Views: 598
Reputation: 295472
Instead of assigning 1
to BASH_XTRACEFD
, make a new file descriptor with a copy of FD 1, and point BASH_XTRACEFD
to that.
exec {BASH_XTRACEFD}>&1
set -x
$(echo "ls") # note that this is bad practice; see BashFAQ #50
That way your command substitutions change the real FD 1, but leave the copy of the original FD 1 alone.
Note that {BASH_XTRACEFD}>&1
-- with no leading $
, and where BASH_XTRACEFD
is not previously defined -- is deliberate and correct syntax! See https://stackoverflow.com/a/41620630/14122 describing this syntax, which requires bash 4.1 or later.
Upvotes: 3