Рубрики
Uncategorized

Написание сценариев Bash, которые не только проводят: проверка башизмов и тестирование с помощью Dash

Сценарии Bash наиболее портативны, когда избегают «башизма». Давайте рассмотрим написание Posix-совместимости, она … Tagged с помощью Bash, Tutorial, Linux, DevOps.

Posix Shell Scripting (2 серии деталей)

Сценарии Bash наиболее портативны, когда избегают «башизма». Давайте рассмотрим написание сценариев Shell-совместимых POSIX, которые работают над Пепел/прибор и другие раковины.

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

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

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

Краткий контрольный список

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

  1. Есть #!/bin/штрих как первая (» hebang «) строка сценария, а не #!/usr/bin/bash или другая оболочка
  2. Избегайте тестов с двумя брекетами [[]] и вместо этого используйте одиночные кронштейны [ ]
  3. Используйте printf вместо echo -e Когда новые линии '\ n' нужно напечатать
  4. Не используйте другое Читать Флаг, кроме -r , как в Читать -r
  5. Избегайте удобных перенаправлений Bash: используйте > MyFile 2> & 1 перенаправить Stdout и stderr на файл, а не &> myfile
  6. Точно проверить с Dash или Шикар: согласованная политика обычная оболочка
  7. Используйте только стандартные флаги и опции с общими утилитами, такими как sed , Греп , вырезать , тест , и другие
  8. Избегайте проблем, обнаруженных Чекбашизмы
  9. Избегайте проблем, обнаруженных Shellcheck

Пример

#!/bin/sh

read -p "Who would you like to greet? "

if [[ -z $REPLY ]] ; then
  recipient="$REPLY"
else
  recipient="World"
fi

echo -e "Hello\n$recipient\n"

Вы можете сохранить следующее в текущем рабочем каталоге по вашему выбору, как Пример-noncompliant.sh

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

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

Dash, Sopix, соответствующий оболочке

Dash является производным Пепел оболочка. Это должно быть Posix -Поллект.

Debian и Ubuntu поставляются с установкой Dash. Фактически, сценарии, вызванные /bin/sh Будет работать с Dash по умолчанию. На Альпийский , Крошечный ядро Linux , OpenWrt и другие дистрибуции, которые используют Busybox По умолчанию стандартная оболочка также является DASH (хотя помечен как ASH ). На федоре может быть установлена с SUDO DNF УСТАНОВКА DASH Анкет Другие дистрибуции также могут включать в себя Dash в их репозиториях.

Используя Docker или Подман , бежать черту легко, как в этом примере:

docker run -it debian dash

Вы также можете попробовать мой Posix Playground Container , с различными инструментами, в том числе Dash Анкет По умолчанию он использует Шикарные: совместимая с политикой обычная оболочка , что немного строче, чем Dash. Его можно запустить с:

docker run -it -v "$PWD:/work" docker.io/bowmanjd/posix-playground

Смотрите статью для более глубокого объяснения.

Во всем вышеперечисленном, Подман может заменить Docker Без проблем.

Тестирование примера

Вы можете попробовать запустить Пример-noncompliant.sh Сценарий выше, но с Dash, а не Bash?

dash example-noncompliant.sh

Или, используя Docker или Podman:

docker run -v "$PWD:/work" -it debian dash /work/example-noncompliant.sh

Вывод, вероятно, напоминает:

dash: 3: read: arg count
dash: 5: [[: not found
-e Hello

Несколько точек обучения могут быть получены из этого вывода.

Избегайте тестов с двумя брекетами [[]]

[[ Construct является безопасной, если использовать Bash или другую оболочку, которая поддерживает башизмы. Он имеет несколько удобных функций, таких как сопоставление с помощью корпорации с использованием = ~ и имеет меньше рисков с сопоставлением струн.

Тем не менее, вы, как правило, не пойдете не так с подходом к одному кронштейну: [] (псевдоним для тест ). Всегда не забудьте процитировать переменные, но в любом случае это хороший совет. Если вам нужно регулярное соответствие экспресса, используйте Греп Анкет

Итог: не все оболочки поддержки [[ ; Используйте [ вместо.

Используйте ванильное чтение

При использовании Читать Команда для получения ввода, вот несколько предложений:

  1. Всегда указывайте переменную, а не полагаясь на дефолт Баша $ Ответ
  2. Используйте Читать -r И никаких других флагов. Используя -r запрещает пользователю использовать Backslash для ухода за символами, что может вызвать проблемы позже. И никакой другой флаг не является Поддерживается Posix Читать Анкет
  3. Вместо того, чтобы указать подсказку с -p , просто используйте printf позвонить до Читать командование Снова Posix Читать не поддерживает такой флаг, плюс -p Вариант означает что -то другое для Zsh’s Читать Анкет

Учитывая эти правила, наш скрипт не должен использовать Читайте -p "Кого бы вы хотели приветствовать?" скорее:

printf "Who would you like to greet? "
read -r recipient

Используйте printf, когда новички решаются

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

Однако, если у нас есть новички в строке, которую мы хотим печатать, или если желать печати без новой линии, то printf , не echo -e Будет нашим другом.

Итак, вместо Echo -e "Привет \ n $ получатель \ n" В нашем коде, выше, это было бы лучше:

printf "Hello\n%s\n\n" "$recipient"

Обратите внимание на замену переменной с %s В первой строке (строка формата). Не кладите переменные раковины, как $ получатель в строке формата. Это способ.

Рефакторирование примера

Учитывая вышеупомянутые проблемы, давайте полностью переписаем наш сценарий приветствия:

#!/bin/sh

printf "Who would you like to greet? "
read -r recipient

if [ -z "$recipient" ] ; then
  recipient="World"
fi

printf "Hello\n%s\n\n" "$recipient"

Вы можете сохранить вышеизложенное с именем файла Пример posix.sh или похожие.

Когда вы запускаете его, ведут ли это так же, как и некоммерческий сценарий?

Удовлетворительный.

Поиск башизмов с контрольными башизмом

В встроен инструмент, встроенный в Debian devscripts Проект, называемый Checkbashisms Анкет Это простой, но мощный Perl Script что вытекает любые башизмы в сценарии раковины, который начинается с #!/bin/sh Шебанг

На Debian и Ubuntu он может быть установлен с Sudo Apt Установка Devscripts и на федоре с Sudo DNF Установка Devscripts-Ceckbashisms Пока альпийский это Sudo Apk Добавить чекбашизмы Анкет Другие дистрибуции могут иметь что -то подобное. Вы также можете попробовать установить Perl, затем загрузить и запустить Sheckbashisms Perl Script сам.

Что происходит, когда вы запускаете его Пример-noncompliant.sh или Пример posix.sh ? Так что рассказываю …

Проведение лучших практик с ShellCheck

Мой новый любимый вспомогатель сценария Shell — Shellcheck . Вы можете вставить свой сценарий оболочки онлайн и проверить его там или установить ShellCheck обычным способом (Debian, Ubuntu, Fedora, Alpine, Archlinux и другие легко доступны в стандартных хранилищах пакетов.)

Он поднимает флаг соответствия POSIX на любых нуждающихся линиях, но также проверяются многие другие проблемы. Ваш код может работать просто отлично, но у вас есть внимание, которые нуждаются в некотором внимании. Shellcheck поможет вам там. Я интегрирую его в свой редактор, чтобы я мог пробиться, пока я набираю.

Измерение против спецификации POSIX

К счастью, POSIX.1-2017 Стандарт открыто задокументирован. Рассмотрим это: при обнаружении и тестировании вариантов для данного инструмента, такого как Читать , Греп , или sed Вместо того, чтобы ходить на страницы GNU, на страницы дистрибутивных управлений, или в документы Bash или ZSH, почему бы не перейти к самой POSIX Spec? Список утилит и их варианты ясно объясняется.

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

Часто я нахожу, что мне не нужно sed -e или grep -e так же плохо, как я думал. Несколько дополнительных экологичных персонажей, и я там.

Рассмотрим другие языки и инструменты конфигурации

Иногда, когда расширенный синтаксис, предоставленный утилитами GNU, оправдан, это может быть признаком того, что правильный инструмент для работы вовсе не является оболочкой и его соотечественниками.

Если ваша система имеет Python , Ruby , Nodejs , или другой любимый язык, может ли это быть более надежным, гибким и последовательным вариантом? Даже в обстоятельствах (встроенных системах), в которых эти время выполнения будут слишком громоздкими, возможно, удаленные сценарии с другой машины, в порядке. Например, можно использовать Python для SSH для удаленной машины, получить необходимую информацию, выполнить некоторую логику, затем отправить соответствующие команды обратно, без необходимости Python на целевой машине.

Это причина, по которой такие инструменты, как Ansible , SaltStack , Шеф -повар и Кукол существует. Они тоже могут быть довольно раздутыми, если потребности просты. Но они непобедимы для гибкости и повторяемости.

Другие источники

В своем исследовании этой статьи я столкнулся с некоторыми ресурсами, которые вы можете найти, по крайней мере, столь же интересными, как и эта:

Пожалуйста, не стесняйтесь поделиться своими советами, вопросами, исправлениями в комментариях!

Posix Shell Scripting (2 серии деталей)

Оригинал: «https://dev.to/bowmanjd/writing-bash-scripts-that-are-not-only-bash-checking-for-bashisms-and-testing-with-dash-1bli»