I have a script launch.sh that executes itself as another user so as to create files with the correct owner. I want to pass -x to this invocation if it was originally passed to the script

if [ `whoami` == "deployuser" ]; then
  ... bunch of commands that need files to be created as deployuser
  echo "Respawning myself as the deployment user... #Inception"
  echo "Called with: <$BASH_ARGV>, <$BASH_EXECUTION_STRING>, <$->"
  sudo -u deployuser -H bash $0 "$@"  # How to pass -x here if it was passed to the script initially?

I've read the bash debugging page but there seems to be no clear option that tells whether the original script was launched with -x.


Many of the flags that can be passed to bash on the command line are set flags. set is the shell built-in which can toggle these flags at runtime. For example, calling a script as bash -x foo.sh is basically the same as doing set -x at the top of the script.

Knowing that set is the shell built-in responsible for this lets us know where to look. Now we can do help set and we get the following:

$ help set
set: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
      -x  Print commands and their arguments as they are executed.
    Using + rather than - causes these flags to be turned off.  The
    flags can also be used upon invocation of the shell.  The current
    set of flags may be found in $-.  The remaining n ARGs are positional
    parameters and are assigned, in order, to $1, $2, .. $n.  If no
    ARGs are given, all shell variables are printed.

So from this we see that $- should tell us what flags are enabled.

$ bash -c 'echo $-'

$ bash -x -c 'echo $-'
+ echo hxBc

So basically you just need to do:

if [[ "$-" = *"x"* ]]; then
  echo '`-x` is set'
  echo '`-x` is not set'

As a bonus, if you want to copy all the flags, you could also do

bash -$- /other/script.sh
|improve this answer|||||
  • 1
    You'll need to use [[ $- == *x* ]] for pattern matching. – glenn jackman Jul 15 '14 at 1:21
  • 1
    Or you could use the standard case $- in *x*) ... ;; *) ... ;; esac. It's useful to know this use of case for scripts that are meant to be portable, and now that I know of it, I find it easier to just remember that, than to remember "if bash-specific, then [[, else case". – hvd Jul 15 '14 at 7:25
  • OK, then this whole series of comments could be deleted. – l0b0 Jul 15 '14 at 8:16
  • $- outputs hB. What do the -h and -B flags/arguments do? Don't see then in the bash man page. – Dan Dascalescu Jul 16 '14 at 0:52

set -o will output xtrace on if -x is used, otherwise xtrace off.

|improve this answer|||||

Although @Patrick 's answer is the "right" one, you can also just pass a parameter or exported variable into your child script that tells it what to do - like turn on tracing.

This has the disadvantage that (I believe) you have to re-export it to each level of script you are about to enter.

It has the advantage of being able to selectively trace (or otherwise affect) just the script(s) you need the output/modified behavior from - to cut down on extraneous output, etc.. E.g. tracing can be off for the calling script and still get turned on in the called script. It's not an all or nothing proposition.

Not part of your question, but related:

I sometimes define a variable like

E="echo "


E=": "

and use it (in multiple statements) like

"${E}" rsync ...

or, just for the second variation,

"${E}" echo "this is a debugging message"

Then, I just comment out the second definition when I want the command(s) to run. You could also use this technique with a parameter or exported variable instead.

With either of these, you have to watch out for compound statements because the method is only guaranteed to work on the first statement in the compound list.

|improve this answer|||||

You could grab the PID of the process and then examine the process table with ps to see what it's arguments were.

|improve this answer|||||
  • You can grab the process' PID via: $$ – Paul Calabro Jul 15 '14 at 1:13
  • 2
    I don't think that's a good idea in general, because if the -x was set inside the script, it will not be shown in ps output. And this solution is inefficient anyway. – vinc17 Jul 15 '14 at 1:14
  • That's a fair argument. I actually didn't know about the $- variable. That seems like a much better approach to solving this. – Paul Calabro Jul 15 '14 at 1:17
  • 1
    There's also the set -o solution I've proposed. It should also work for options that do not have an associated flag like -x. – vinc17 Jul 15 '14 at 1:19

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.