chizou
chizou

Reputation: 1272

Can I set BASH_XTRACEFD=1 without breaking command substitution?

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

Answers (1)

Charles Duffy
Charles Duffy

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

Related Questions