March 1

Лайфхаки по написанию скриптов на Bash, которые должен знать каждый разработчик

Это перевод оригинальной статьи Bash Scripting Hacks Every Developer Should Know.

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

Небольшие хитрости Bash, которые сэкономят часы, предотвратят катастрофы и незаметно улучшат рабочий процесс разработчика.

Введение: Bash — это навык, который вы, сами того не зная, игнорировали.

Большинство разработчиков «знают» Bash так же, как и Git: ровно столько, чтобы справляться. Несколько команд в памяти. Скрипт скопирован со Stack Overflow. Молитва перед нажатием Enter.

Но Bash — это не просто язык программирования для энтузиастов Linux или специалистов по DevOps. Это невидимая сила, стоящая за автоматизацией, отладкой, деплоями, обработкой данных и бесчисленным количеством повседневных задач. Разница между медленным разработчиком и пугающе эффективным часто сводится к тому, насколько хорошо он владеет shell’ом.

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

Давайте прокачаем вашу интуицию.

1. Всегда запускайте скрипты в «строгом режиме».

Большинство скриптов Bash завершаются с ошибкой без предупреждения. Это опасно.

Первый полезный совет, который должен знать каждый разработчик, — это включение строгого режима в начале скриптов:

set -euo pipefail

Вот что делает эта единственная строка:

  • -e: В случае сбоя команды немедленно завершить работу.
  • -u: Cчитает необъявленные переменные ошибкой
  • -o pipefail: пайплайн считается упавшим, если любая команда завершилась с ошибкой.

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

Считайте это превращением runtime-ошибок в compile-time-ошибки для Bash.

2. Используйте "$@" вместо $* (Да, это важно)

Если ваш скрипт принимает аргументы, эта деталь может сэкономить вам часы отладки.

Всегда используйте:

"$@"

Вместо:

$*

Почему? Потому что "$@" сохраняет границы аргументов. Пробелы остаются неизменными. Имена файлов не распадаются на части. Ваш скрипт работает корректно, когда пользователи передают строки в кавычках.

Это одно из тех правил Bash, которое кажется излишне педантичным — пока из-за них не ломается что-то важное в продакшене.

3. Давайте своим переменным точные имена

В Bash нет типов, но имена — это ваша система безопасности.

Плохо:

x=10
y="file.txt"

Лучше:

MAX_RETRIES=10
INPUT_FILE="file.txt"

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

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

4. Используйте $(...) вместо обратных кавычек.

Если вы всё ещё используете обратные кавычки, пора от них отказаться.

Старый вариант:

files=`ls`

Современный вариант:

files=$(ls)

Замена команд с помощью $(...) выглядит следующим образом:

  • Легче читать
  • Легче вкладывается
  • Менее подвержен ошибкам

Речь идёт не просто о предпочтениях в синтаксисе. Речь идёт о написании кода на Bash, который не будет создавать проблем по мере своего развития.

5. Быстро выявляйте ошибки с помощью явных сообщений об ошибках.

Если что-то пошло не так, в вашем скрипте должно быть указано, почему.

Вместо того чтобы позволять Bash загадочным образом завершать работу с ошибкой, сделайте следующее:

command || {
  echo "❌ Failed to run command"
  exit 1
}

А ещё лучше — оберните это в функцию:

die() {
  echo "Error: $1" >&2
  exit 1
}

Теперь ваши скрипты не просто терпят неудачу — они умеют доносить информацию. И вы в будущем поблагодарите себя в настоящем за эту ясность.

6. Используйте функции (даже в небольших скриптах).

Многие разработчики избегают использования функций в Bash, считая их излишними.

Нет.

Функции позволяют вам:

  • Избегать дублирования
  • Инкапсулировать логику
  • Сделать скрипты читаемыми от начала до конца.

Пример:

cleanup() {
  rm -rf /tmp/my_app
}

Вам не нужен объектно-ориентированный Bash. Вам нужна лишь структура. Функции — это самый простой способ добиться успеха.

7. Перехватывайте сигналы как профессионал

Случалось ли вам когда-нибудь сталкиваться с тем, что скрипт оставляет незавершенные файлы после нажатия Ctrl+C?

Это потому, что вы не перехватили сигналы.

trap cleanup EXIT INT TERM

Это гарантирует, что ваша логика очистки будет выполнена даже в случае неожиданного завершения работы скрипта.

Ловушки необходимы для:

  • Временных файлов
  • Файлов блокировки
  • Фоновых процессов

Они превращают сценарии, в которых "надеемся, ничего не пойдет не так", в сценарии, в которых "готовы к хаосу".

8. Кавычьте переменные так, будто от этого зависит ваша работа

В Bash не заключенные в кавычки переменные — это мины замедленного действия.

Плохой:

rm $file

Хороший:

rm "$file"

Если переменная $file содержит пробелы, символы шаблона или пуста, отсутствие кавычек может привести к потере данных.

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

Одна эта привычка предотвращает одни из самых страшных shell-багов, каких только можно себе представить.

9. Используйте массивы вместо строк, разделённых пробелами.

Bash поддерживает массивы. Используйте их.

Вместо:

files="a.txt b.txt c.txt"

Сделайте следующее:

files=("a.txt" "b.txt" "c.txt")

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

Циклы становятся безопаснее:

for file in "${files[@]}"; do
  echo "$file"
done

Как только вы научитесь правильно использовать массивы, вы уже никогда не захотите возвращаться к прежнему способу работы.

10. Читайте файлы построчно правильно.

Это классическая ловушка.

Неправильно:

for line in $(cat file.txt); do

Верно:

while IFS= read -r line; do
  echo "$line"
done < file.txt

Правильный подход:

  • Сохраняет пробелы
  • Не зависает при работе со специальными символами.
  • Эффективно работает с большими файлами

Это может показаться многословным, но это единственный безопасный способ.

11. Используйте set -x для тонкой отладки

Когда скрипт работает некорректно, догадки не помогут.

Включить трассировку выполнения:

set -x

Bash выводит каждую команду перед её выполнением. Это бесценно для:

  • Падений в CI
  • Неожиданных значений переменных
  • Логических ошибок

Вы даже можете включить его временно:

set -x
# debug section
set +x

Это встроенный отладчик Bash. Используйте его.

12. Предпочитайте [[ ... ]] вместо [ ... ]

Тестовые выражения старого образца ненадежны.

Используйте:

if [[ "$a" == "$b" ]]; then

Вместо:

if [ "$a" = "$b" ]; then

Почему?

  • Без разделения слов
  • Более безопасное сравнение строк
  • Поддержка регулярных выражений
  • Меньше проблем с кавычками

[[ ... ]] — это одно из лучших улучшений Bash. Воспользуйтесь им.

13. Используйте Here-Docs для корректного многострочного ввода.

Когда в скрипты начинают встраиваться SQL-запросы, файлы конфигурации или большие текстовые блоки, читаемость ухудшается.

Here-docs это исправляет:

cat <<EOF > config.yaml
port: 8080
env: production
EOF

Они идеально подходят для:

  • Шаблонов
  • Docker-конфигураций
  • Встроенной документации

Читаемый Bash — это поддерживаемый Bash.

14. Делайте скрипты самодокументируемыми

Добавьте --help флаг.

Серьезно.

if [[ "$1" == "--help" ]]; then
  echo "Usage: script.sh [options]"
  exit 0
fi

Даже короткое описание использования резко повышает удобство — для коллег и для вас из будущего.

Профессиональные скрипты объясняют себя сами.

15. Относитесь к скриптам Bash как к настоящему программному обеспечению.

Это самый главный хак.

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

Сделайте следующее:

  • Используйте систему контроля версий.
  • Добавляйте комментарии там, где их смысл не очевиден.
  • Проводите рефакторинг по мере роста скриптов.
  • Тестируйте в чистых окружениях

Bash поощряет дисциплину. Игнорируйте её, и он даст отпор.

Вывод: Bash — это инструмент, многократно увеличивающий эффективность.

Bash-скриптинг — это не про то, чтобы стать рок-звездой терминала. Bash-скриптинг — это про то, чтобы сделать вашу рабочую жизнь проще. Отправка сообщения в Slack. Загрузка случайной шутки в ваши сообщения. Поиск случайной картинки для добавления в ваши сообщения.

Вам не обязательно быть экспертом во всех аспектах Bash. Всё, что вам нужно, — это несколько полезных навыков и уверенность в их применении.

Терминал — это место, где выполняются команды, но именно там сосредоточено влияние.

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

На этом все! Спасибо за внимание! Если статья была интересна, подпишитесь на телеграм-канал usr_bin, где будет еще больше полезной информации.