Is it possible to test whether a bash script was executed with -x?
I'm writing a script which also runs some remote scripts, and I'd like to be able to do something like:
USE_X="$( run_with_x && "-x" || "" )"
ssh $host "bash $USE_X some_script.sh"
Just look at the $- variable.
USE_X=`case "$-" in *x*) echo "-x" ;; esac`
(Yup, I did manage to do that without invoking grep. Save the pids!)
case $- in *x*) USE_X="-x";; *) USE_X=;; esac @bbaja42 It doesn't expand to anything: it's a pattern that the string $- is matched against.
*) USE_X=;; changes nothing, if USE_X was not set previously. Also, the whole case construct is unnecessary (see my version - isn't that simpler?)
USE_X has been initialized earlier on. I don't consider your version simpler: it's a few characters shorter (and even then only if USE_X has been initialized, otherwise it's longer), but at the expense of clarity and portability.
USE_X is not necessary for the purpose of OP's intended use (to pass $USE_X to further scripts). Using case construct looks less clear and natural than a regular condition evaluation in my view.
This expression will be true if the script is run with -x, false otherwise: [[ $- =~ x ]]
So this expression will be "-x" if the script is run with -x and "" (empty) otherwise: $([[ $- =~ x ]] && echo "-x")
${-//[^x]} If you assign this to variable, like: x=${-//[^x]} then the following expression will be empty when there was no x and -x otherwise: ${x:+-x} Combine like: x=${-//[^x]} USE_X=${x:+-x} Or if you don't want to use an extra variable, you can reuse USE_X: USE_X=${-//[^x]} USE_X=${USE_X:+-x} This is much much faster than doing a regular expression comparison! (But less readable just looking at the code, figuring out what it does...)
Probably the simplest way of parsing $-, similar to dagbrown's method (also pure bash), but without using case and backticks (subshell):
if [[ ${-/x} != $- ]] ; then USE_X="-x"; fi
or even shorter:
[[ ${-/x} != $- ]] && USE_X="-x"
Note that [[ is not an invocation of test builtin program (as is the case with [), but a bash syntax construct (according to man bash and this dev recommendation). So I claim it to be "purer bash" ;)
After reading man pages and grepping for things, here's the solution:
$ cat show_x.sh
#!/bin/bash
if [ "$(set | grep xtrace)" ]; then
echo "xtrace is on. :D"
else
echo "xtrace is off. :("
fi
Result:
$ bash show_x.sh
xtrace is off. :(
$ bash -x show_x.sh
++ set
++ grep xtrace
+ '[' SHELLOPTS=braceexpand:hashall:interactive-comments:xtrace ']'
+ echo 'xtrace is on. :D'
xtrace is on. :D
The bash man page documents set -o xtrace as equivalent to set -x, which in turn is equivalent to giving -x as an argument to the shell. (So far, this is compatible with SUSv3 sh, with the caveat that -o option is required "if the system supports the User Portability Utilities option".)
Also, set -o without an option prints the current status of all of the -o options. (SUSv3 specifies this as well, but not usefully; the format is unspecified, so you can only depend on it if you know you're running a shell that uses a format similar to bash's.)
So, the pipeline set -o | grep xtrace | grep -q on should be what you're looking for.