Сила 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 выполняет сейчас, и с какими параметрами. Это незаменимо для поиска ошибок и понимания того, что происходит в скрипте шаг за шагом.
Изучите остальные опции set — это совсем другой уровень контроля и понимания скриптов.
Ясные параметры команд — залог читаемости и хорошего стиля
В Linux команды часто довольствуются одной буквой вместо параметра — так короче, но через пару месяцев не всегда понятно, что именно делает эта часть скрипта.
Если есть возможность, используйте длинные параметры команд, которые начинаются с двойного тире и логично описывают свою функцию. Такой код легко читать и поддерживать.
В повседневной работе сокращения удобны, но если ваш скрипт увидит кто-то кроме вас — выбирайте длинные параметры. Это стандарт чистого кода.
Используйте современное $(...) для подстановки команд
Чтобы сохранить результат выполнения команды в переменную, есть два способа:
Оба будут работать, но предпочтительнее современный вариант с $(...). Способ с обратными кавычками — пережиток прошлого: вложенность с ним реализовать непросто, а читать такой код неудобно.
Удобно задавайте значения переменных по умолчанию
Полезный приём: задать переменной значение по умолчанию прямо в одну строку, без лишних условий. Например:
В этом случае CMD примет значение переменной PAGER, если она есть, а иначе — "more".
Можно создавать более сложные вложенные конструкции для приоритета: сначала аргумент из командной строки, затем переменная окружения, и только потом дефолтное значение.
Файлы с дефисом в начале? Всегда добавляйте двойное тире!
Как и пробелы, необычные символы (например, дефис в начале имени) могут вызвать массу хлопот при работе с файлами. Например, файл с именем «-rf» существует в каталоге как ни в чём не бывало, но команда ls справиться с ним не сможет:
Если попытаться работать с таким именем, появится ошибка:
Почему? Команды вроде ls воспринимают любой аргумент с дефисом в начале как опцию, а не имя файла. А теперь представьте, если такой файл "-rf" окажется в rm!
Лучше избегать таких имён, но в скриптах обязательно вставляйте двойное тире после параметров команд. Например:
Двойное тире даёт командному интерпретатору понять: дальше — только имена файлов и аргументы, никакие не опции, и этим спасает от критических ошибок.
Локальные переменные в функциях — ваше скрытое преимущество
Глобальные переменные — источник коварных багов даже для опытных скриптеров. В Bash по умолчанию переменные глобальные, даже если объявлены внутри функции.
Стоит случайно переиспользовать переменную в разных частях скрипта, и можно получить весьма неожиданные последствия.
Чтобы такого не случилось, всегда объявляйте переменные внутри функций как локальные:
Если вам понравилась эта статья, подпишитесь, чтобы не пропустить еще много полезных статей!
Премиум подписка - это доступ к эксклюзивным материалам, чтение канала без рекламы, возможность предлагать темы для статей и даже заказывать индивидуальные обзоры/исследования по своим запросам!Подробнее о том, какие преимущества вы получите с премиум подпиской, можно узнать здесь
Также подписывайтесь на нас в:
- Telegram: https://t.me/gergenshin
- Youtube: https://www.youtube.com/@gergenshin
- Яндекс Дзен: https://dzen.ru/gergen
- Официальный сайт: https://www-genshin.ru