When setting "set -x" inside bash script, or if you run your script with bash -x, you will get all the arguments printed to the screen together with the stdout.

Is it possible to have stderr and stdout printed to screen but redirecting the set -x output to the log file without having it printed to the screen?

The idea is to have all the info I can get inside the log, but only print regular stdout and stderr to the screen.

user1@mac1:~/tmp$ cat t1.sh
exec 4>shell.log

set -x
echo abc
cat ffff

user1@mac1:~/tmp$ bash t1.sh
cat: ffff: No such file or directory
user1@mac1:~/tmp$ cat shell.log
+ echo abc
+ cat ffff
  • is it possible to do this also in bash version that does not support BASH_XTRACEFD ? i mean is there any other way to overcome this when BASH_XTRACEFD is not available? – Asaf Magen Dec 6 '15 at 13:26
  • why don't you try @PSkocik 's suggestion. – X Tian Dec 7 '15 at 14:22

The set -x output goes to stderr. What you need to do is redirect stderr, e.g.:

sh -x your_script.sh 2> debug_info.txt

If you want to distinguish the stderr output due to set -x from normal stderr output , you can utilize the fact that set -x output is prefixed with $PS4, which defaults to +.

bash -x your_script.bash 2> \
    >(tee >/dev/null \
           >(grep    '^\+ ' > set_x_output.txt)\
           >(grep -v '^\+ ' > rest_of_sdterr.txt)\

If some of your normal stderr output begins with +, you can change the default prefix by changing PS4.

  • like i wrote i dont want to loose stderr not printed to screen in case i have errors in my script. – Asaf Magen Oct 14 '15 at 14:56
  • This redirects the rest of stderr to rest_of_sderr.txt if you use /dev/tty, it'll go back to the terminal or you can do bash -x your_script.bash 3>2 2> ... and then replace rest_of_stderr.txt with &3. – PSkocik Oct 14 '15 at 15:08
  • X Tian's solution is more terse for bash. This will work with a sh script too. – PSkocik Oct 14 '15 at 15:08

i've manage to fix my redirection with this command:

  • its also let me control exactly what i'm excluding.
  • this is only for bash version older then 4.1 where BASH_XTRACEFD is not valid.

exec 2> >(tee -a $LOG_FULL_NAME 2>&1 | grep -v "^+ \|^++ ") 1>&2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.