Как отладить скрипт bash? [закрыто]

159

Есть ли способ отладки скрипта bash? Например, что-то, что печатает что-то вроде журнала выполнения, например, «вызывающая линия 1», «вызывающая линия 2» и т. Д.

Corvus
источник
2
Здесь есть похожий вопрос: serverfault.com/questions/16204/…
приостановлен до дальнейшего уведомления.

Ответы:

195
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, которые он вообще не распознает. (В Solaris /bin/shэто оболочка Bourne; в современном Linux это иногда Dash - меньшая, более строгая оболочка только для POSIX.) При вызове по имени, подобному этому, строка 'shebang' (' #!/bin/bash' vs '#!/bin/sh')

В руководстве по Bash есть раздел, посвященный режиму Bash POSIX, в котором, вопреки давней, но ошибочной версии этого ответа (см. Также комментарии ниже), подробно описывается различие между «Bash, вызываемым как sh», и «Bash, вызываемым как bash».

При отладке сценария оболочки (Bash) будет разумно и разумно - даже необходимо - использовать оболочку, названную в строке shebang, с -xопцией. В противном случае вы можете (будете?) Вести себя иначе при отладке при запуске скрипта.

Джонатан Леффлер
источник
1
Он определил bashсценарий. А запуск скрипта bash sh -xприведет к тому, что он будет вести себя совершенно иначе! Пожалуйста, обновите свой ответ.
1
1
@lhunath: Каким образом sh -x (или bash -x) заставляет скрипт вести себя совершенно иначе? Очевидно, он выводит информацию трассировки в stderr; это данность (хотя и не упоминается в моем ответе). А что еще? Я использую 'bash' как 'sh' в Linux и MacOS X и не заметил серьезной проблемы.
Джонатан Леффлер
6
Есть различия, при запуске и во время выполнения. Они полностью документированы в дистрибутиве Bash.
TheBonsai
4
Вот ссылка на документ bash: gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files 'Если Bash вызывается с именем sh, он пытается имитировать поведение при запуске исторических версий sh как настолько близко, насколько это возможно, и в то же время соответствует стандарту posix »
thethinman
6
И используйте приглашение PS4, чтобы предоставить более полезную информацию, например:export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
estani
28

Я использовал следующие методы для отладки моего скрипта.

set -eзаставляет скрипт немедленно остановиться, если какая-либо внешняя программа возвращает ненулевой статус выхода. Это полезно, если ваш сценарий пытается обработать все случаи ошибок, и если неудача должна быть выполнена.

set -x было упомянуто выше и, безусловно, является наиболее полезным из всех методов отладки.

set -n также может быть полезно, если вы хотите проверить ваш скрипт на наличие синтаксических ошибок.

straceТакже полезно посмотреть, что происходит. Особенно полезно, если вы сами не написали сценарий.


источник
1
Создание сценария (т.е. создание оболочки, выполняющей сценарий) является странным методом отладки оболочки (но может работать для ограниченного набора проблем).
TheBonsai
1
Я признаю, что это странно и очень многословно, но если вы ограничите вывод strace несколькими системными вызовами, это станет полезным.
1
Обратите внимание, что strace -fэто необходимо, если вы также хотите найти ошибки в процессах, запускаемых скриптом. (что делает его во много раз более многословным, но все же полезно, если вы ограничите его системными вызовами, которые вас интересуют).
Random832
set -eявляется ... спорным .
Чарльз Даффи
12

Этот ответ действителен и полезен: https://stackoverflow.com/a/951352

Но я считаю, что «стандартные» методы отладки скриптов неэффективны, не интуитивно понятны и сложны в использовании. Для тех, кто привык к сложным отладчикам с графическим интерфейсом, которые держат все под рукой и делают работу проще для простых проблем (и возможно для сложных проблем), эти решения не очень удовлетворительны.

Я использую комбинацию DDD и bashdb. Первый выполняет последний, а второй выполняет ваш сценарий. Это обеспечивает многооконный интерфейс с возможностью пошагового просмотра кода в контексте и просмотра переменных, стека и т. Д. Без постоянных умственных усилий для сохранения контекста в вашей голове или повторного перечисления источника.

Руководство по его настройке приведено здесь: http://ubuntuforums.org/showthread.php?t=660223

Stabledog
источник
Только что обнаружил DDD благодаря вашему ответу. В Ubuntu 12.04.3 (64bit) версия apt-sources не работает. Мне пришлось скомпилировать и установить из исходного кода, чтобы начать отладку моего bash-скрипта. Инструкции здесь - askubuntu.com/questions/156906/… помогли.
хронодекар
Да, это проблема. Я решил это некоторое время назад с помощью некоторых сценариев - 'dddbash' устанавливает / собирает DDD, удаляет старую версию, если она неверна, устанавливает bashdb и т. Д. (Ответ был отредактирован с этой информацией сейчас)
Stabledog
10

Вы также можете написать «set -x» в скрипте.

Cheeto
источник
4
И вы можете написать 'set + x', чтобы отключить его.
Джонатан Леффлер
10

Я нашел утилиту 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

найди сейчас!

Это всего лишь маленький пример.

Решатель уравнений
источник
1
И это онлайн !
Ник Вестгейт,
К счастью, инструмент развился до такой степени, что он также находит оставшуюся ошибку.
tripleee
3

Установите VSCode , затем добавьте расширение отладки bash, и вы готовы к отладке в визуальном режиме. Смотрите здесь в действии.

введите описание изображения здесь

yantaq
источник
3

Используйте 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

Дитрих Шрофф
источник
2
Это только пограничный ответ (см. Также здесь ). Вы должны расширить свой ответ, включив в него как можно больше информации, по крайней мере, минимум, необходимый для того, чтобы действительно выполнить то, что вы предлагаете, и использовать ссылки только для справки. По сути, сообщения о переполнении стека (и все в стеке обмена) должны быть автономными. Это означает, что в вашем ответе должно быть достаточно информации, чтобы читателю не нужно было уходить за пределы сайта для получения указаний. Прямо сейчас, это не тот случай для этого ответа.
Макьен
это первый ответ, который я нашел после просмотра многих, который фактически показывает, что настоящая отладка возможна. Стандартные ответы «set + x» идеально соответствуют самодостаточному ответу, но почти намеренно игнорируют истинные вопросы об истинной отладке. Я приветствую этот ответ 👏
simbo1905
2

Я построил отладчик Bash. Просто попробуйте. Я надеюсь, что это поможет https://sourceforge.net/projects/bashdebugingbash

abadjm
источник
BDB в настоящее время поддерживается на английском и испанском языках. Чтобы изменить язык, отредактируйте файл / etc / default /
bdb
скриншот выглядит интересно, но я не могу заставить его работать "bdb.sh: строка 32: bdbSTR [1]: несвязанная переменная"; Кстати, он будет показывать текущие значения всех установленных переменных каждый шаг, который мы делаем в коде?
Водолей Сила
2

установите + x = @ECHO OFF, установите -x = @ECHO ON.


Вы можете добавить -xvопцию к стандартному Шебангу следующим образом:

#!/bin/bash -xv  

-x: Показать команды и их аргументы по мере их выполнения.
-v: Показать строки ввода оболочки, как они читаются.


ltraceэто еще один Linux утилита аналогична strace. Однако ltraceперечисляет все вызовы библиотеки, вызываемые в исполняемом или запущенном процессе. Само его название происходит от отслеживания вызовов библиотеки. Например:

ltrace ./executable <parameters>  
ltrace -p <PID>  

Источник

Premraj
источник
1

Я думаю, что вы можете попробовать этот отладчик Bash: http://bashdb.sourceforge.net/ .

Нань Сяо
источник
Существует большое количество подробностей о регистрации сценариев оболочки через глобальные переменные оболочки. Мы можем эмулировать подобный вид регистрации в сценарии оболочки: cubicrace.com/2016/03/efficient-logging-mechnism-in-shell.html
Piyush Chordia
1

Какой-то трюк для отладки скрипты:

С помощью 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-скрипты

Ф. Хаури
источник
0

Существует большое количество подробностей о регистрации сценариев оболочки через глобальные переменные оболочки. Мы можем эмулировать подобный вид регистрации в сценарии оболочки: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html

В этом посте есть подробности об уровнях логирования, таких как INFO, DEBUG, ERROR. Отслеживание таких деталей, как запись скрипта, выход скрипта, запись функции, выход из функции.

Пример журнала:

введите описание изображения здесь

Пиюш Чордия
источник