Comments 37
Отличная идея! Можно ещё позволить выполнять команды перед каждой строкой:
function _debug_for_bash() {
echo "# $BASH_COMMAND";
while read -p "debug> " _cmnd; do
if [ -n "$_cmnd" ]; then
eval "$_cmnd";
else
break;
fi;
done
}
trap '_debug_for_bash' DEBUG
А ещё можно сделать скрипт, который будет всё это делать для другого скрипта.
Пожалуй причешу и утащу в блог, с указанием авторства оригинала, разумеется.
У меня всё и началось именно с них - я использовал read в этом качестве, добавляя его везде, где хотелось, чтоб была точка останова. Эдакий аналог Octave-ского keyboard.
Ну вот это может оказаться очень тяжеловесно... Если @selivanov_pavel сделает в виде отдельного скрипта, тогда и хорошо. А если таскать из скрипта в скрипт много строк кода, тогда, возможно, и не стоит.. впрочем, тут дело вкуса и того, как оно будет реализовано. Не готов заранее оценивать юзабельность этого.
Вот спасибо хорошо! Я пытался подобное сделать, но моего баш кунг фу в сочетании с тем, что было достаточно приведённого решения, не хватило для того, чтоб закончить.
Когда напишете в блог, пожалуйста, пришлите ссылку, я её добавлю сюда, чтоб те, кто находят эту статью, могли и на вашу быстро перейти. Или сами добавьте, пожалуйста.
Пост: https://selivan.github.io/2022/05/21/bash-debug.html
Скриптик для отладки других скриптов: https://github.com/selivan/bash-debug
while read -r -e -p "$(echo -e "\e[0;31m${_bash_debug_last_retcode//0/$(echo -e "\e[0;32m#\e[0m")}\e[0m \e[1m$BASH_COMMAND\e[0m") " _bash_debug_command; do
if [ -n "$_bash_debug_command" ]; then
eval "$_bash_debug_command";
else
break;
fi;
done
Если добавлять цвета, то тогда можно выводить красным ненулевой код и зелёным - нулевой. PR приветствуются: https://github.com/selivan/bash-debug
А можно просто отлаживать скрипты включив режим отладки bash
set -x
Или можно совместить с холостым выполнением bash
set -n
Я искренне думал, что эта статья сведётся к строчке
set -euxo pipefail
К сожалению, опция -x не даёт отладки по шагам, а лишь печатает то, что выполняется. Кому-то удобно, кому-то нет. Я принципиально не стал освещать разные опции баша, чтоб не отвлекать от основной идеи.
Про опцию -n я не слышал. Спасибо, попробую.
Всё ниже указанное стоит рассматривать как мой личный опыт, и моё мнение может не совпадать с мнением коллег, потому не стоит воспринимать как истину последней инстанции.
С bash я работаю плотно с 2009 года. За это время я имел опыт работы с perl, python, awk, sed, jq, bc, dc, grep и прочими типичными инструментами связанными с работой в эмуляторах терминала. На протяжении этого периода стиль моего написания скриптов менялся несколько раз. На данный момент те задачи, которые я решаю с помощью bash, не требуют контроля пошагового выполнения, и этому есть три причины.
Во-первых, из всех написанных мною скриптов, используемые по сей день скрипты отличаются прямолинейностью алгоритма. По мере получения опыта я стараюсь сводить к минимуму использования условных операторов, циклов и других элементов контроля выполнения. Например, по циклам предел вложенности в моих скриптах очень редко достигает трёх циклов, обычно не больше двух. Если задача требует более сложных структур, я разделяю её на несколько маленьких скриптиков. Я предпочитаю именно несколько скриптиков в отдельных файлах вместо использования функций в одном файле. Если задача требует алгоритмов из алгоритмизации или, не дай бог, вычислительной математики. Например, для поиска всех пересечений двух кубических кривых безье, вместо bash я отдал бы предпочтение чему-либо другому. И даже дело не в том, что bash скуден на инструментарий решения математики. Объединяя средства bash, perl, awk, grep мощность обработки строк и манипуляций с текстовыми или полу-текстовыми потоками с лихвой компенсирует слабую математическую сторону bash. Простые скрипты с линейным алгоритмом на bash хочется использовать снова и снова. А когда в скрипте десятки точек выхода, рекурсивных вызовов, бесконечных циклов, такие скрипты пишутся на один раз. А потом, открыв такой скрипт даже вспоминать не хочется, что сам там накодил.
Во-вторых, не смотря на линейность алгоритма, скрипты могут быть большими, и их может быть много. Например, рабочая сборка livecd содержит более 250 пакетов из AUR. Это же сколько тысяч раз мне надо нажать на Enter, пока сформируется репозиторий с актуальными версиями рабочего софта!
В-третьих, если запустить bash без параметров, он как раз откроется в похожем режиме. Бонусом этого режима является возможность контролировать ход выполнения скрипта, задавая новые значения переменным и редактируя команды скрипта. Побочным эффектом такого подхода будет необходимость искусно манипулировать историей команд и реверсивным поиском. Ну, или копировать-вставлять в окно эмулятора терминала по-командно. Тоже опыт. Кстати, именно в таком режиме я веду разработку особо длинных команд bash.
Завершить свой монолог хочу действительно правильным советом и напутствием. Пишите скрипты на bash только для собственного использования на подконтрольных вам компьютерах и серверах. А когда будете писать скрипты с расчетом того, что их будут запускать другие люди на других разных компьютерах, такие скрипты пишите на sh. Да, там нет того синтаксического сахара bash. Скрипты на sh пишутся чуть дольше и чуть длиннее. Но это время окупится. Не сомневайтесь! Коллеги в чужих скриптах разбираться не любят. Скинут вывод ошибки, которую вы часами будете пытаться воспроизвести. А в итоге выяснится, что запускают скрипт на каком-нибудь osx или каким-нибудь древним busybox. Рано или поздно все приходят к sh. Back to the primitive (c)Soulfly. А для своих нужд я лично уже наверное года 4 пользуюсь fish. Пробовал zsh - мне лично не зашёл. У fish лучший autocomplete по клавише Tab прямо из коробки. Но скрипты все равно пишу на bash/sh.
Также ещё хочется дать напутствие. Попробуйте разобраться как работает readline. Вы им пользуетесь каждый рабочий день, но никогда не задумывались о нём. Этот чёрный ящик линукса вообще мало кто любит трогать. В коде так почти ничего не поменяли с 90х годов. Попробуйте, например, поменять сигналы на другие комбинации клавиш, а Ctrl+x забиндить вырезать, Ctrl+c - скопировать, Ctrl+v - вставить, Ctrl+z - отменить, Ctrl+a - выделить всё. К тому моменту когда у вас получится это сделать, вы будете гораздо больше понимать в терминалах и, собственно, почему их эмулируют. Эх, может через пару-тройку лет настанет день, и я напишу огромнейший пост про readline.
Было бы круто! Про readline я пытался начинать читать, но как-то, видимо, не в то время.
По поводу линейности скриптов - полностью поддерживаю. Лично я отлаживал сценарии плдготовки релиза - скрипт, который на ветках запускает тесты, мержит с веток в мастер, запускает тесты на мастере и добавляет метку релиза, но не пушит, пушу я руками, если всё ок.
Т.е. скрипт прямолинейный и простой. И пользуюсь им только я.
Недавно мне надо было написать скрипт для docker alpine и я так и не смог нагуглить какой-нибудь нормальный cheat sheet для sh, так как в выдаче поиска был один только bash. Пришлось добавить apk add --no-cache bash
.
Кто-нибудь может поделиться ссылкой на удобный справочник по sh?
Лучший справочник по sh (без шуток)
man sh
Если не пользовались ранее:
man man
Или вместо консольной версии man можно использовать веб-версию. Можно начинать со второго раздела Shell command language.
Всем спасибо за ссылки! Но сожалению, для меня они все большие и неудобные справочники, а не шпаргалки, как например вот эта по bash https://gist.github.com/lee2sman/423ef08fc2318969b3eaaf5d1e14e02e
Каждый сам - кузнечик своего счастья. Возьмите, сделайте одну удобную книжку, люди вам спасибо скажут.
А ваш чит шит - это… ну, такое себе. Про перенаправление поговорили, а такой постоянно используемый конструкт, как `2>&1` забыли. `sort | uniq ` - это смешно. Разве `sort -u` не короче? Про то, что '[' - это отдельная программа (утилита) - не сказали. Как и про то, что можно писать (например) `if kill -0 $$; then echo "I'm alive, alive!"; fi`. Про `&&`/`||` сказали, а про то, что там есть маааленькая такая особенность их взаимодействия - не упомянули.
Эта напоминалка для тех, кто прочёл документацию, знает, как это работает, просто каждый день этим не пользуется и что-то может подзабыть. У меня такая же есть, но выкладывать её в паблик смысла нет - там всё очень специфичное.
Мой совет - прочтите документацию один раз, получите общее представление о возможностях, а потом уже можете пользоваться подсказками, понимая, что в них написано, а не слепо копируя чьи-то ошибки.
А когда будете писать скрипты с расчетом того, что их будут запускать
другие люди на других разных компьютерах, такие скрипты пишите на sh.
Только не sh, а dash. sh - это символическая ссылка на bash или dash (в зависимости от системы).
Без настроенного PS4 этого мало для эффективной отладки
bashdb ?
Если ваш скрипт надо отлаживать, то его стоило бы написать на нормальном языке
есть bash script debug extension для VSCode и там реализованы все нужные вещи - step over, step in, breakpoints и т.п.:
https://marketplace.visualstudio.com/items?itemName=rogalmic.bash-debug
еще есть в природе bash debug project для любителей консоли:
http://bashdb.sourceforge.net/
имея эти две вещи можно забыть про извращения вида "как еще сделать отладочный вывод (prinf после каждой строчки) более похожим на нормальную отладку" описанные в статье :)
Про плагин для vscode не знал. В хорошее время мы живём... ничего делать не надо - надо просто найти то, что уже кем-то сделано до нас.
Использование плагина vscode ограничивает выбор окружения, отладить скрипт на сервере уже не получится.
Отлаживать неотлаженные скрипты на проде - не лучшая затея.
VS Code умеет открывать SSH сессии
Как отлаживать bash-script-ы по шагам или, возможно, самая короткая статья о программировании/отладке на Хабре