После того, как я опубликовал предыдущую статью, в которой рассказал о том, какие приёмы применяю, создавая Shell-скрипты, отличающиеся отличным UX, сообщество Hacker News поделилось со мной ценными откликами и предложениями. Я оформил то, что мне удалось узнать, в виде новой статьи, разобрав здесь ещё шесть приёмов, которые позволят всем желающим улучшить свои скрипты.

1. Делайте свои скрипты пригодными для работы в различных окружениях и приспособленными для использования в конвейерах
Обращайте особое внимание на то, чтобы ваши скрипты хорошо работали бы в различных окружениях. Вот четыре основных приёма, которые позволяют этого добиться.
a) Используйте #!/usr/bin/env bash
Конструкция #!/usr/bin/env bash
позволяет системе использовать переменную пользователя PATH
для поиска исполняемого файла bash
. Польза этого приёма очевидна, если принять во внимание то, что в разных системах оболочка bash
может быть установлена в различных местах.
А вот конструкция #!/bin/bash
непосредственно задаёт место, в котором нужно искать bash
. В некоторых системах эта конструкция может оказаться неработоспособной.
b) Применяйте tput для организации переносимого цветового кодирования выходных данных скриптов
Вот пример:
if command -v tput &>/dev/null && [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
RESET=$(tput sgr0)
else
RED=""
GREEN=""
RESET=""
fi
c) С уважением относитесь к переменной окружения $NO_COLOR
Как показано выше — перед использованием цветов проверьте переменную $NO_COLOR
.
d) Выводите сообщения об ошибках в stderr
Пример:
echo "Error: Invalid input" >&2
2. Используйте printf вместо echo
Команда echo
может, в различных условиях, вести себя не так, как ожидается, особенно — при установке определённых флагов или при выводе специальных символов. А вот команда printf
в разных системах ведёт себя более предсказуемо:
printf "Hello, %s!\n" "$name"
3. Используйте shellcheck для поиска проблем в Shell-скриптах
ShellCheck — это потрясающий инструмент, который позволяет выявлять в Shell-скриптах распространённые проблемы. Например — он обратил моё внимание на следующую конструкцию, способную превратиться в проблему, когда анализировал мой скрипт evaluate.sh
:
# До
rm -rf $dir/*
# После (Предложение ShellCheck)
rm -rf "$dir"/*
Всегда прогоняйте свои скрипты через ShellCheck перед тем, как сочтёте их готовыми к работе.
4. Помните о разнице между двойными и одинарными квадратными скобками
Двойные скобки — [[]]
— это расширение bash
, которое даёт больше возможностей, чем одинарные скобки — []
. Их применение обычно позволяет сделать код безопаснее и гибче. Вот основные отличия разных конструкций из квадратных скобок:
# Сопоставление с шаблоном при использовании одинарных скобок не работает
file="my-special-file.txt"
if [ "$file" = *.txt ]; then # Всегда false! Выполняется строковое сравнение
echo "Single brackets don't do pattern matching"
fi
if [[ $file == *.txt ]]; then # Работает! Выполняется сопоставление с шаблоном
echo "Double brackets support pattern matching"
fi
# Различается поведение при разделении слов
path="/some path/with spaces"
if [ -d "$path" ]; then # Переменную нужно заключать в кавычки
echo "Single brackets need quotes"
fi
if [[ -d $path ]]; then # Кавычки необязательно (но рекомендованы)
echo "Double brackets handle spaces"
fi
# Логические операторы ведут себя по-разному
if [ "$a" = "1" ] && [ "$b" = "2" ]; then # Нужны операторы оболочки
echo "Single brackets use shell && ||"
fi
if [[ $a == 1 && $b == 2 ]]; then # Можно использовать встроенные операторы
echo "Double brackets have logical operators"
fi
# Регулярные выражения работают лишь в двойных скобках
if [[ $number =~ ^[0-9]+$ ]]; then # Поддержка регулярных выражений
echo "Double brackets support regex with =~"
fi
Двойные скобки прощают больше оплошностей и обладают более широкими возможностями, чем одинарные. Но они работают только в оболочке bash
. Если вам нужно, чтобы ваши скрипты были бы POSIX-совместимыми (чтобы они работали в других оболочках — вроде dash
или sh
) — используйте одинарные скобки. А в остальных случаях двойные скобки обычно удобнее и позволяют писать более безопасный код.
Обратите внимание на то, что даже при использовании двойных скобок хорошим тоном считается заключение имён переменных в кавычки. Делается это для того, чтобы скрипты, написанные для разных оболочек, выглядели бы единообразно, и для того, чтобы избежать неприятных сюрпризов при модификации существующих скриптов.
5. При возникновении ошибок, связанных с неправильным использованием команд, применяйте команду exit 2 вместо команды exit 1
Общепринятым является подход, когда, если возникают синтаксические ошибки при использовании командной строки, применяется код выхода 2:
if [ $# -eq 0 ]; then
echo "Usage: $0 <argument>" >&2
exit 2
fi
6. Используйте шаблоны bash-скриптов
Шаблоны bash-скриптов могут помочь в создании надёжной базы для ваших собственных разработок. Один из популярных вариантов таких шаблонов — bash3boilerplate
. Вот — простой пример:
#!/usr/bin/env bash
set -o errexit
set -o pipefail
set -o nounset
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
__base="$(basename ${__file} .sh)"
arg1="${1:-}"
# Тут будет ваш код
Итоги
Если вам было интересно узнать об этих приёмах — можете почитать мою предыдущую статью. Там подняты следующие темы:
Всеобъемлющая обработка ошибок и проверка входных данных
Понятные выходные данные, оформляемые с использованием разных цветов
Подробные сведения о ходе работы скрипта
Стратегический подход к обработке ошибок с помощью set -e и set +e
Адаптация скрипта к различным платформам
Использование временных меток при сохранении в файлах результатов множества вызовов скрипта
Кроме того — можете заглянуть на страницу Hacker News с обсуждением той статьи, которое вдохновило меня на написание этого материала.
Благодарю сообщество Hacker News за ценные советы. Удачи всем в написании скриптов!
О, а приходите к нам работать? ? ?
Мы в wunderfund.io занимаемся высокочастотной алготорговлей с 2014 года. Высокочастотная торговля — это непрерывное соревнование лучших программистов и математиков всего мира. Присоединившись к нам, вы станете частью этой увлекательной схватки.
Мы предлагаем интересные и сложные задачи по анализу данных и low latency разработке для увлеченных исследователей и программистов. Гибкий график и никакой бюрократии, решения быстро принимаются и воплощаются в жизнь.
Сейчас мы ищем плюсовиков, питонистов, дата-инженеров и мл-рисерчеров.
amarkevich
в контейнерах часто отсутствует bash, поэтому лучше по возможности делать скрипты на sh