Найти в Дзене
Герман Геншин

10 простых привычек, которые гарантированно спасут ваши Bash-скрипты от фатальных ошибок

Сила Bash-скриптов впечатляет, но за ней стоит и высокая ответственность: малейшая оплошность в коде может привести к настоящей катастрофе. Куда разумнее сразу привыкнуть писать скрипты аккуратно и безопасно. К счастью, Bash изначально оснащён множеством инструментов для защиты ваших сценариев. Большинство из них — это современные подходы, которые пришли на смену старым, не всегда надёжным решениям. Применяйте эти советы, чтобы избавляться от багов, проще отлаживать код и справляться с неожиданностями уверенно. Самая важная строка любого shell-скрипта — это shebang-комментарий, который определяет, каким интерпретатором будет запускаться код. Без неё скрипт не будет самостоятельным и не сможет явно указывать свой язык. Существует два популярных способа задать shebang. Первый вариант: В этом случае скрипт всегда запустится через bash из /bin/bash — почти всегда работает без сюрпризов. Второй способ чаще выбирают опытные пользователи: Здесь команда env ищет bash в текущем PATH. Это как в
Оглавление

Сила Bash-скриптов впечатляет, но за ней стоит и высокая ответственность: малейшая оплошность в коде может привести к настоящей катастрофе. Куда разумнее сразу привыкнуть писать скрипты аккуратно и безопасно.

К счастью, Bash изначально оснащён множеством инструментов для защиты ваших сценариев. Большинство из них — это современные подходы, которые пришли на смену старым, не всегда надёжным решениям. Применяйте эти советы, чтобы избавляться от багов, проще отлаживать код и справляться с неожиданностями уверенно.

Всё начинается с правильного shebang — укажите интерпретатор чётко

Самая важная строка любого shell-скрипта — это shebang-комментарий, который определяет, каким интерпретатором будет запускаться код. Без неё скрипт не будет самостоятельным и не сможет явно указывать свой язык.

Существует два популярных способа задать shebang. Первый вариант:

В этом случае скрипт всегда запустится через bash из /bin/bash — почти всегда работает без сюрпризов. Второй способ чаще выбирают опытные пользователи:

Здесь команда env ищет bash в текущем PATH. Это как ввести команду в терминале — запустится та версия bash, которая найдётся первой (например, из ~/bin вместо /bin). Такой подход универсальнее: скрипт сработает, даже если bash установлен не в стандартной директории.

Однако shebang с /bin/bash гарантирует запуск именно нужной версии интерпретатора, не позволяя другой bash неожиданно повлиять на ваш скрипт. Такой вариант надёжнее.

Сказать, что один способ универсально лучше, нельзя: всё зависит от ваших задач. Для личных скриптов, как правило, разницы нет.

Не забывайте про кавычки для переменных — мелочь, которая спасает от ошибок

Одна из самых частых ловушек в Bash — проблемы с пробелами, которые делят аргументы команд. Стоит забыть про кавычки при использовании переменных — и появятся странные ошибки.

Сравните:

Если подставить переменную без кавычек, Bash вставит содержимое как есть, и если в значении есть пробелы, команда "увидит" несколько отдельных аргументов.

В итоге команда будет, например, думать, что работает с тремя файлами вместо одного.

Чтобы этого не случилось, окружайте переменные кавычками:

Иногда дополнительно используют фигурные скобки:

В данном случае это не обязательно, но если к имени переменной примыкает ещё какой-то текст — скобки действительно выручают.

Без скобок Bash подумает, что речь о совсем другой переменной, и выдаст ошибку.

Пусть скрипт сам завершает работу при сбое — не замалчивайте ошибки

Самая коварная ситуация — когда команда сработала с ошибкой, а скрипт продолжает работать дальше, словно ничего не случилось. Такая проблема легко остаётся незамеченной, если явным образом не проверять статус выполнения каждой команды. Тут нас спасает опция:

Официально она делает следующее:

Сразу завершает выполнение скрипта, если любая команда (или цепочка команд) вернула ошибку (ненулевой статус).

По сути: скрипт автоматически прервётся там, где случилась ошибка, а вы не предусмотрели обработку. Пример:

Здесь ожидается, что команда touch выполнится нормально — но это не всегда так.

Добавьте set -e — и если возникнет ошибка, выполнение остановится:

Команда set меняет поведение оболочки. Важна ещё опция pipefail:

Теперь ошибка на любом этапе цепочки сразу прерывает скрипт, а не остаётся незамеченной.

Отслеживайте ошибки осознанно — управляйте потоком вручную

Автоматическое завершение — это страховка, но грамотный скрипт всегда обрабатывает ключевые ошибки самостоятельно. Для этого используйте переменную статуса выполнения $?

А ещё проще — логические операторы Bash:

Включайте отладку: режим xtrace покажет, где зарылась ошибка

Весьма полезная опция оболочки — xtrace:

С ней на экране видно, какую команду Bash выполняет сейчас, и с какими параметрами. Это незаменимо для поиска ошибок и понимания того, что происходит в скрипте шаг за шагом.

-2

Изучите остальные опции set — это совсем другой уровень контроля и понимания скриптов.

Ясные параметры команд — залог читаемости и хорошего стиля

В Linux команды часто довольствуются одной буквой вместо параметра — так короче, но через пару месяцев не всегда понятно, что именно делает эта часть скрипта.

Если есть возможность, используйте длинные параметры команд, которые начинаются с двойного тире и логично описывают свою функцию. Такой код легко читать и поддерживать.

В повседневной работе сокращения удобны, но если ваш скрипт увидит кто-то кроме вас — выбирайте длинные параметры. Это стандарт чистого кода.

Используйте современное $(...) для подстановки команд

Чтобы сохранить результат выполнения команды в переменную, есть два способа:

Оба будут работать, но предпочтительнее современный вариант с $(...). Способ с обратными кавычками — пережиток прошлого: вложенность с ним реализовать непросто, а читать такой код неудобно.

Удобно задавайте значения переменных по умолчанию

Полезный приём: задать переменной значение по умолчанию прямо в одну строку, без лишних условий. Например:

В этом случае CMD примет значение переменной PAGER, если она есть, а иначе — "more".

Можно создавать более сложные вложенные конструкции для приоритета: сначала аргумент из командной строки, затем переменная окружения, и только потом дефолтное значение.

Файлы с дефисом в начале? Всегда добавляйте двойное тире!

Как и пробелы, необычные символы (например, дефис в начале имени) могут вызвать массу хлопот при работе с файлами. Например, файл с именем «-rf» существует в каталоге как ни в чём не бывало, но команда ls справиться с ним не сможет:

-3

Если попытаться работать с таким именем, появится ошибка:

-4

Почему? Команды вроде ls воспринимают любой аргумент с дефисом в начале как опцию, а не имя файла. А теперь представьте, если такой файл "-rf" окажется в rm!

Лучше избегать таких имён, но в скриптах обязательно вставляйте двойное тире после параметров команд. Например:

Двойное тире даёт командному интерпретатору понять: дальше — только имена файлов и аргументы, никакие не опции, и этим спасает от критических ошибок.

Локальные переменные в функциях — ваше скрытое преимущество

Глобальные переменные — источник коварных багов даже для опытных скриптеров. В Bash по умолчанию переменные глобальные, даже если объявлены внутри функции.

Стоит случайно переиспользовать переменную в разных частях скрипта, и можно получить весьма неожиданные последствия.

Чтобы такого не случилось, всегда объявляйте переменные внутри функций как локальные:

Если вам понравилась эта статья, подпишитесь, чтобы не пропустить еще много полезных статей!

Премиум подписка - это доступ к эксклюзивным материалам, чтение канала без рекламы, возможность предлагать темы для статей и даже заказывать индивидуальные обзоры/исследования по своим запросам!Подробнее о том, какие преимущества вы получите с премиум подпиской, можно узнать здесь

Также подписывайтесь на нас в: