Как я могу узнать, был ли запущенный в данный момент bash-скрипт вызван с -x для отладки?

11

У меня есть скрипт, launch.shкоторый выполняется как другой пользователь, чтобы создавать файлы с правильным владельцем. Я хочу передать -x на этот вызов, если он был первоначально передан в сценарий

if [ `whoami` == "deployuser" ]; then
  ... bunch of commands that need files to be created as deployuser
else
  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?
fi

Я прочитал страницу отладки bash, но, похоже, нет четкой опции, которая сообщала бы, был ли запущен оригинальный скрипт -x.

Дан Дакалеску
источник

Ответы:

15

Многие из флагов, которые могут быть переданы bashв командной строке, являются setфлагами. setвстроенная оболочка, которая может переключать эти флаги во время выполнения. Например, при вызове сценария , как bash -x foo.shв основном так же , как делают set -xв верхней части сценария.

Знание того set, что встроенная оболочка отвечает за это, позволяет нам знать, где искать. Теперь мы можем сделать help setи получаем следующее:

$ 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.
...

Итак, из этого мы видим, что $-должны сказать нам, какие флаги включены.

$ bash -c 'echo $-'
hBc

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

Так что в основном вам просто нужно сделать:

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

В качестве бонуса, если вы хотите скопировать все флаги, вы также можете сделать

bash -$- /other/script.sh
Патрик
источник
1
Вам нужно будет использовать [[ $- == *x* ]]для сопоставления с образцом.
Гленн Джекман
1
Или вы можете использовать стандарт case $- in *x*) ... ;; *) ... ;; esac. Полезно знать это использование caseдля сценариев, которые должны быть переносимыми, и теперь, когда я знаю об этом, мне легче просто запомнить это, чем помнить «если специфичен для bash, то [[еще case».
HVd
Хорошо, тогда вся эта серия комментариев может быть удалена.
10
$-выходы hB. Что делают -hи -Bфлаги / аргументы? Не смотрите на страницу руководства bash .
Дан Даскалеску
3

set -oвыдаст, xtrace onесли -xиспользуется, в противном случае xtrace off.

vinc17
источник
2

Хотя ответ @Patrick является «правильным», вы также можете просто передать параметр или экспортированную переменную в свой дочерний скрипт, который скажет ему, что делать - например, включить трассировку.

Это имеет тот недостаток, что (я считаю) вы должны реэкспортировать его на каждый уровень сценария, который вы собираетесь ввести.

Он имеет то преимущество, что может выборочно отслеживать (или иным образом влиять) только те сценарии, для которых нужно выводить / изменять поведение - для сокращения посторонних выводов и т. Д. Например, для вызывающего сценария может быть отключена трассировка все еще включается в вызываемом скрипте. Это не предложение «все или ничего».

Не часть вашего вопроса, но связанная:

Я иногда определяю переменную как

E=""
E="echo "

или

E=""
E=": "

и использовать его (в нескольких утверждениях), как

"${E}" rsync ...

или, только для второго варианта,

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

Затем я просто закомментирую второе определение, когда хочу выполнить команду (и). Вы также можете использовать эту технику с параметром или экспортированной переменной.

С любым из них вы должны следить за составными операторами, потому что метод гарантированно будет работать только с первым оператором в составном списке.

Джо
источник
1

Вы можете получить PID процесса, а затем просмотреть таблицу процессов с помощью ps, чтобы увидеть, каковы ее аргументы.

Пол Калабро
источник
Вы можете получить процесс 'PID через: $$
Пол Калабро
2
Я не думаю, что это хорошая идея в целом, потому что если она -xбыла установлена ​​внутри скрипта, она не будет отображаться в psвыходных данных. И это решение в любом случае неэффективно.
vinc17
Это справедливый аргумент. Я на самом деле не знал о переменной $. Это кажется намного лучшим подходом к решению этой проблемы.
Пол Калабро
1
Есть также set -oрешение, которое я предложил. Он также должен работать для опций, которые не имеют связанных флагов, таких как -x.
vinc17