Есть ли способ отладить bash script? Например, что-то, что печатает какой-то журнал выполнения, например "вызывающая строка 1", "вызывающая строка 2" и т.д.
Как отладить bash script?
Ответ 1
sh -x script [arg1 ...]
bash -x script [arg1 ...]
Это дает вам след того, что выполняется. (См. Также "Уточнение" в нижней части ответа.)
Иногда вам нужно управлять отладкой в script. В этом случае, поскольку Cheeto напомнил меня, вы можете использовать:
set -x
Это включает отладки. Затем вы можете отключить его с помощью:
set +x
(Вы можете узнать текущее состояние трассировки, проанализировав $-
, текущие флаги, для x
.)
Кроме того, оболочки обычно предоставляют опции "-n
" для "без выполнения" и "-v
" для режима "verbose"; вы можете использовать их в сочетании, чтобы узнать, может ли оболочка считать, что он может выполнить ваш script - иногда полезно, если у вас есть несбалансированная цитата где-то.
Существует утверждение, что опция < -x
в Bash отличается от других оболочек (см. комментарии). Bash Manual говорит:
-
-x
Распечатайте трассировку простых команд, команд
for
, командcase
, командselect
и арифметических командfor
, а также их аргументов или связанных списков слов после их расширения и перед их выполнением. Значение переменнойPS4
расширяется, и итоговое значение выводится перед командой и ее расширенными аргументами.
Это, по-видимому, не указывает на другое поведение вообще. Я не вижу никаких других ссылок на "-x
" в руководстве. Он не описывает различия в последовательности запуска.
Уточнение: в таких системах, как типичный Linux-блок, где "/bin/sh
" является символической ссылкой на "/bin/bash
" (или везде, где найден исполняемый файл Bash), две командной строки достигают эквивалентного эффекта запустив script с трассировкой выполнения. В других системах (например, Solaris и некоторых более современных вариантах Linux) /bin/sh
не Bash, и две командной строки будут давать (слегка) разные результаты. Прежде всего, "/bin/sh
" будет путать конструкции в Bash, которые он вообще не распознает. (В Solaris, /bin/sh
- оболочка Bourne, в современной Linux иногда Dash - меньшая, более строго оболочка POSIX). При вызове по имени, подобным этому, строка "shebang" ('#!/bin/bash
' vs '#!/bin/sh
') в начале файла не влияет на интерпретацию содержимого.
В руководстве Bash есть раздел Bash POSIX mode, который, вопреки давней, но ошибочной версии этого ответа (см. также комментарии ниже), подробно описывает разницу между Bash, вызываемой как sh
'и Bash, вызываемой как bash
'.
При отладке оболочки (Bash) script разумно и разумно - необходимо даже - использовать оболочку, названную в строке shebang, с опцией -x
. В противном случае вы можете (будете?) Получать другое поведение при отладке при запуске script.
Ответ 2
Я использовал следующие методы для отладки моего script.
set -e
немедленно отключает script, если какая-либо внешняя программа возвращает ненулевой статус выхода. Это полезно, если ваш script пытается обрабатывать все случаи ошибок и где отказ сделать это должен быть захвачен.
set -x
упоминалось выше и, безусловно, является самым полезным из всех методов отладки.
set -n
также может быть полезна, если вы хотите проверить свои ошибки в синтаксисе script.
strace
также полезно посмотреть, что происходит. Особенно полезно, если вы не написали script самостоятельно.
Ответ 3
Этот ответ действителен и полезен: fooobar.com/questions/916/...
Но я нахожу, что методы "стандартного" script отладки неэффективны, неинтуитивны и сложны в использовании. Для тех, кто привык к сложным отладчикам GUI, которые ставят все на кончиках ваших пальцев и делают работу легкой задачей для простых проблем (и, возможно, для сложных проблем), эти решения не очень удовлетворительны.
Я использую комбинацию DDD и bashdb. Первый выполняет последний, а второй выполняет ваш script. Это обеспечивает многооконный пользовательский интерфейс с возможностью перехода через код в контекст и просмотр переменных, стека и т.д. Без постоянного умственного усилия по поддержанию контекста в вашей голове или повторному перечислению источника.
Есть рекомендации по настройке здесь: http://ubuntuforums.org/showthread.php?t=660223
Ответ 4
Вы также можете записать "set -x" в script.
Ответ 5
Я нашел утилиту shellcheck и, возможно, некоторые люди находят ее интересной https://github.com/koalaman/shellcheck
Маленький пример:
$ cat test.sh
ARRAY=("hello there" world)
for x in $ARRAY; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in $ARRAY; do
^-- SC2128: Expanding an array without an index only gives the first element.
исправить ошибку, сначала попробуйте...
$ cat test.sh
ARRAY=("hello there" world)
for x in ${ARRAY[@]}; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in ${ARRAY[@]}; do
^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.
Повторите попытку...
$ cat test.sh
ARRAY=("hello there" world)
for x in "${ARRAY[@]}"; do
echo $x
done
$ shellcheck test.sh
найдите сейчас!
Это лишь небольшой пример.
Ответ 6
Я построил отладчик Bash. Просто попробуй. Надеюсь, это поможет https://sourceforge.net/projects/bashdebugingbash
Ответ 7
Установите VSCode, затем добавьте расширение bash debug, и вы готовы отлаживаться в визуальном режиме. см. Здесь в действии.
Ответ 8
Я думаю, вы можете попробовать этот отладчик Bash: http://bashdb.sourceforge.net/.
Ответ 9
set + x = @ECHO OFF, установите -x = @ECHO ON.
Вы можете добавить опцию -xv
к стандартному Shebang следующим образом:
#!/bin/bash -xv
-x
: отображать команды и их аргументы по мере их выполнения. -v
: отображать строки ввода оболочки во время их чтения.
ltrace
- это еще одна утилита Linux, подобная strace
. Тем не менее, ltrace
перечисляет все вызовы библиотеки, вызываемые в исполняемом файле или запущенном процессе. Его имя происходит от трассировки библиотеки. Например:
ltrace ./executable <parameters>
ltrace -p <PID>
Ответ 10
Есть много подробностей о регистрации для скриптов оболочки через глобальные переменные оболочки. Мы можем эмулировать аналогичный вид ведения журнала в оболочке script: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
Сообщение содержит информацию об интродуцированных уровнях журнала, таких как INFO, DEBUG, ERROR. Детали трассировки, такие как запись script, выход script, ввод функции, выход функции.
Пример журнала:
Ответ 11
Некоторые трюки для отладки bash скрипты
Использование set -[nvx]
В дополнение к
set -x
и
set +x
для остановки дампа.
Я хотел бы поговорить о set -v
, где дамп меньше, чем менее развитый вывод.
bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21
for arg in x v n nx nv nvx;do echo "- opts: $arg"
bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
set -$arg
for i in {0..9};do
echo $i
done
set +$arg
echo Done.
eof
sleep .02
done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5
Переменные дампа или трассировка на лету
Для тестирования некоторых переменных я иногда использую это:
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args
для добавления:
declare >&2 -p var1 var2
в строке 18 и запуская результат script (с аргументами), без необходимости редактировать их.
конечно, это можно было бы использовать для добавления set [+-][nvx]
:
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args
добавит declare -p v1 v2 >&2
после строки 18, set -x
до строки 22 и set +x
до строки 26.
маленький образец:
bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
seq -f 'echo [email protected], $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8
Примечание. Уход за $LINENO
будет зависеть от изменений "на лету"!
(Чтобы увидеть результат script без выполнения, просто снимите bash <(
и ) arg1 arg2
)
Шаг за шагом, время выполнения
Ответ 12
Используйте eclipse с обтекаемыми плагинами и baschclipse.
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
Для обледенения: загрузите zip и импортируйте его в eclipse с помощью справки → установите новое программное обеспечение: локальный архив. Для basheclipse: скопируйте банки в каталог распаковки eclipse
Следуйте инструкциям https://sourceforge.net/projects/basheclipse/files/?source=navbar
Я написал учебник со многими снимками экрана http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html
Ответ 13
Запись сообщений об ошибках Bash
Скрипт оболочки представляет собой текстовый файл, содержащий команды оболочки. По умолчанию интерпретатор команд и утилиты оболочки отображают сообщения об ошибках и диагностические сообщения при стандартной ошибке. Bash может печатать трассировку работающего скрипта, если включена опция xtrace
.
Пример кода печатает трассировку в файле xtrace.log
. Функция err
позволяет быстро идентифицировать сообщения об ошибках. Трассировка функции err
отменяется, поскольку ее текущая среда выполнения скрывает информацию, которая формирует трассировку.
Образец кода
#!/bin/bash
set -o errexit
exec 4>xtrace.log
BASH_XTRACEFD=4
PS4='+ $0: line ${LINENO}: ${FUNCNAME[0]}: '
set -x
echo 'Welcome!'
err()
{
printf "%s\n" "${BASH_SOURCE[0]}: line ${BASH_LINENO[0]}: ${FUNCNAME[0]}: $1"
} >&2 4>/dev/null
err 'oops, something went wrong!'
Этот пример кода выводит:
prompt% my_script
Welcome
./my_script: line 16: err: oops, something went wrong!
Сообщения об ошибках могут быть перенаправлены, чтобы скрыть диагностические сообщения:
prompt% my_script 2>err.log
Welcome!
Посмотрите на сообщение об ошибках слежения и просмотра и диагностические сообщения:
prompt% cat xtrace.log
+ ./my_script: line 9: main: echo Welcome
+ ./my_script: line 16: main: err 'oops, something went wrong!'
prompt% cat err.log
./my_script: line 16: err: oops, something went wrong!