Bash ERR trap сбрасывает значение аргументов ошибочной команды - PullRequest
1 голос
/ 02 марта 2020

A bash Ловушка ERR может использоваться для печати трассировки стека функций, ведущих к ERR. Однако действительная команда, которая не выполнена, похоже, не сохраняет свои ARGS в BASH_ARGV или FUNCNAME. Вместо этого есть имя ловушки.

BASH_COMMAND содержит имя и аргументы «выполняемой в данный момент команды», не включая ловушку. Похоже, что это сработает, но содержит нерасширенные переменные.

Есть ли что-то вроде BASH_COMMAND с расширенными переменными или BASH_ARGV с «выполняемой в данный момент командой»?

trace() {
 echo '${FUNCNAME[@]}' ${FUNCNAME[@]}
 echo '${BASH_ARGV[@]}' "${BASH_ARGV[@]}"
 echo '$BASH_COMMAND' "$BASH_COMMAND"
}
trap trace ERR
set -Ee
shopt -s extdebug

f1() {
 false these args are not especially this: $my_arg
}
my_arg=abc
f1 these args are in the trace $my_arg

output:

${FUNCNAME[@]} trace f1 main
${BASH_ARGV[@]} abc trace the in are args these
$BASH_COMMAND false these args are not especially this: $my_arg

В строке примера 2 отображает расширенное «ab c» вызова функции f1, но не «ложное». В строке 3 отображаются аргументы 'false', но не расширенный my_arg.

Ответы [ 2 ]

1 голос
/ 06 марта 2020

Есть ли что-то вроде BASH_COMMAND с расширенными переменными или BASH_ARGV с «выполняемой в данный момент командой»?

Я считаю, что краткий ответ - нет, к сожалению. Но в зависимости от вашего варианта использования есть несколько вариантов.

Самый простой подход - использовать set -x для регистрации важных вызовов. Это, очевидно, работает, только если вы заранее знаете, какие вызовы вам нужны, но аналогичным образом записываете команды как выполненные. Вы можете использовать подоболочку, то есть ( set -x; my_command ... ) для регистрации просто рассматриваемой команды.

Если вы хотите войти в систему только ERR, как вы делаете здесь, вы можете по крайней мере, проверьте BASH_ARGV / BASH_ARGCextdebug), чтобы увидеть функции и другие подпрограммы в стеке. Это не поддерживает произвольные команды, но поскольку оно содержит параметры , переданные в каждый кадр стека, все аргументы раскрываются.

Это предлагает потенциальный обходной путь: сделайте интересующую вас команду в функции! добавление false() { command false "$@"; } в ваш скрипт должно дать вам необходимую информацию. Конечно, это немного утомительно, поэтому мы можем сделать обертку общего назначения для любых интересующих нас команд, если не возражаем против небольшого eval -ing:)

function_wrapper() {
  for cmd in "$@"; do
    eval "${cmd}() { command ${cmd} \"$@\"; }"
  done
}

function_wrapper true false ...

Мы могли бы украсить все встроенные оболочки так, как мы хотели:

while read -r _ cmd; do
  eval "${cmd}() { command ${cmd} \"$@\"; }"
done < <(enable -a)

Будь это хорошая идея или нет, я ' оставлю до вас :)

1 голос
/ 05 марта 2020
  • Я изменил trace(), чтобы посмотреть, есть ли переменные, содержащие расширенную команду false.

    trace() {
      declare -p | grep especially
    }
    

    Вывод:

    
    

    Никаких кубиков.

  • Изменение его для поиска abc говорит нам, если что-то содержит расширенную команду f1:

    trace() {
      declare -p | grep abc
    }
    

    Вывод:

    declare -a BASH_ARGV=([0]="abc" [1]="trace" [2]="the" [3]="in" [4]="are" [5]="args" [6]="these")
    declare -- _="abc"
    declare -- my_arg="abc"
    

    Просто BASH_ARGV. Вот и все.

  • Я думал, что DEBUG ловушки могут содержать больше информации, чем ERR, но изменение trap trace ERR на trap trace DEBUG привело к тем же результатам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...