Как отладить скрипт bash?
Есть ли способ отладки скрипта bash? Например, что-то, что печатает что-то вроде журнала выполнения, например, "вызывающая линия 1", "вызывающая линия 2" и т. Д.
12 ответов
sh -x script [arg1 ...]
bash -x script [arg1 ...]
Они дают вам след того, что выполняется. (См. Также "Разъяснение" в нижней части ответа.)
Иногда вам нужно контролировать отладку в скрипте. В этом случае, как напомнил Cheeto, вы можете использовать:
set -x
Это включает отладку. Затем вы можете выключить его снова с помощью:
set +x
(Вы можете узнать текущее состояние трассировки, проанализировав $-
, текущие флаги, для x
.)
Кроме того, оболочки обычно предоставляют варианты-n
"за неисполнение" и "-v
для "многословного" режима; Вы можете использовать их в комбинации, чтобы увидеть, думает ли оболочка, что она может выполнить ваш скрипт - иногда полезно, если у вас где-то есть несбалансированная цитата.
Существует утверждение, что-x
Вариант в Bash отличается от других оболочек (см. комментарии). Руководство Bash говорит:
-Икс
Распечатать трассировку простых команд,
for
команды,case
команды,select
команды и арифметикаfor
команды и их аргументы или связанные списки слов после их раскрытия и до того, как они будут выполнены. ЗначениеPS4
переменная раскрывается, и результирующее значение выводится перед командой и ее расширенными аргументами.
Кажется, что это вовсе не указывает на другое поведение. Я не вижу других релевантных ссылок на-x
в руководстве. Это не описывает различия в последовательности запуска.
Пояснение: в таких системах, как типичная коробка Linux, где '/bin/sh
это символическая ссылка на/bin/bash
' (или где бы ни находился исполняемый файл Bash), две командные строки обеспечивают эквивалентный эффект запуска сценария с отслеживанием выполнения. В других системах (например, Solaris и некоторых более современных вариантах Linux), /bin/sh
не Bash, и две командные строки дали бы (немного) разные результаты. В частности,/bin/sh
'будет сбит с толку конструкциями в Bash, которые он вообще не распознает. (На Солярисе, /bin/sh
является оболочкой Борна; в современном Linux это иногда Dash - меньшая, более строго POSIX-оболочка.) Когда вызывается по имени, как это, строка 'shebang' ('#!/bin/bash
против '#!/bin/sh
') в начале файла не влияет на то, как содержимое интерпретируется.
В руководстве по Bash есть раздел, посвященный режиму Bash POSIX, в котором, вопреки давней, но ошибочной версии этого ответа (см. Также комментарии ниже), подробно описывается различие между "Bash, вызываемым как sh
'и' Bash вызывается как bash
".
При отладке сценария оболочки (Bash) будет разумно и разумно - даже необходимо - использовать оболочку, названную в строке shebang с -x
вариант. В противном случае вы можете (будете?) Вести себя иначе при отладке при запуске скрипта.
Я использовал следующие методы для отладки моего скрипта.
set -e
заставляет скрипт немедленно останавливаться, если какая-либо внешняя программа возвращает ненулевой статус выхода. Это полезно, если ваш сценарий пытается обработать все случаи ошибок, и если неудача должна быть устранена.
set -x
было упомянуто выше и, безусловно, является наиболее полезным из всех методов отладки.
set -n
также может быть полезно, если вы хотите проверить ваш скрипт на наличие синтаксических ошибок.
strace
Также полезно посмотреть, что происходит. Особенно полезно, если вы сами не написали сценарий.
Этот ответ является действительным и полезным: /questions/43414513/kak-otladit-skript-bash/43414521#43414521
Но я считаю, что "стандартные" методы отладки скриптов неэффективны, не интуитивно понятны и сложны в использовании. Для тех, кто привык к сложным отладчикам с графическим интерфейсом, которые держат все под рукой и делают работу проще для простых проблем (и возможно для сложных проблем), эти решения не очень удовлетворительны.
Я использую комбинацию DDD и bashdb. Первый выполняет последний, а второй выполняет ваш сценарий. Это обеспечивает многооконный интерфейс с возможностью пошагового просмотра кода в контексте и просмотра переменных, стека и т. Д. Без постоянных умственных усилий для сохранения контекста в вашей голове или повторного перечисления источника.
Руководство по его настройке приведено здесь: http://ubuntuforums.org/showthread.php?t=660223
Я нашел утилиту 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
найди сейчас!
Это всего лишь маленький пример.
Используйте Eclipse с плагинами и панцирями.
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
Для шелушения: Загрузите zip и импортируйте его в eclipse с помощью справки -> установите новое программное обеспечение: локальный архив Для basheclipse: Скопируйте файлы jar в каталог dropins eclipse
Следуйте инструкциям на https://sourceforge.net/projects/basheclipse/files/?source=navbar
Я написал учебник со многими скриншотами на http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html
Я построил отладчик Bash. Просто попробуйте. Я надеюсь, что это поможет https://sourceforge.net/projects/bashdebugingbash
установите +x = @ECHO OFF, установите -x = @ECHO ON.
Можете добавить -xv
Вариант к стандартному Шебангу выглядит следующим образом:
#!/bin/bash -xv
-x
: Показать команды и их аргументы по мере их выполнения.-v
: Показать строки ввода оболочки, как они читаются.
ltrace
другая утилита Linux похожа на strace
, Тем не мение, ltrace
перечисляет все вызовы библиотеки, вызываемые в исполняемом или запущенном процессе. Само его имя происходит от отслеживания вызовов библиотеки. Например:
ltrace ./executable <parameters>
ltrace -p <PID>
Существует большое количество подробностей о регистрации сценариев оболочки через глобальные переменные оболочки. Мы можем эмулировать подобный вид регистрации в сценарии оболочки: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
В этом посте есть подробности об уровнях логирования, таких как INFO, DEBUG, ERROR. Отслеживание таких деталей, как запись скрипта, выход скрипта, запись функции, выход из функции.
Пример журнала:
Я думаю, что вы можете попробовать этот отладчик Bash: http://bashdb.sourceforge.net/.
Некоторые хитрости для отладки скриптов 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 и запустив полученный скрипт (с аргументами), не редактируя их.
конечно, это можно использовать для добавления 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 $@, $((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
Будут затронуты изменения на лету!
(Чтобы увидеть полученный скрипт без выполнения, просто удалите bash <(
а также ) arg1 arg2
)
Шаг за шагом, время выполнения
Посмотрите на мой ответ о том, как профилировать bash-скрипты
Напишите сообщения об ошибках 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!