Вы когда -нибудь хотели выполнить одну команду, если другая потерпела неудачу? Или одна команда, только если первая преуспела? Как насчет параллельного исполнения?
Bash и другие популярные оболочки такие как Zsh и Пепел/прибор Имейте несколько полезных, но иногда запутанных операторов для выполнения команд.
В чем разница между &&
, &
,
и
;
Очень короткий чит -лист:
- Используйте
&&
выполнить одну команду только тогда, когда преуспевает предыдущая. - Используйте
- выполнить одну команду только тогда, когда предыдущий сбой.
- Объедините вышеприведенное для условного ветвления.
Используйте
; Чтобы присоединиться к двум командам, когда вы хотите, чтобы второе выполнило Независимо от - результат первого.
Используйте
&Запустить первое задание в фоновом режиме, пока следующее выполняется. Следуйте за всем с
Подождите
Выполнить, если предыдущая команда преуспевает: &&
При выполнении одной команды иногда желательно выполнить другую команду, если и только тогда, когда первая была успешной.
Допустим, мы хотим создать домашний каталог пользователя, если и только тогда, когда этот пользователь уже существует. Мы можем проверить наличие пользователя с id
, затем, если успешно, создайте домашний каталог, тогда, если это Успешен, напишите .bashrc
файл:
id fredflintstone && mkdir /home/fredflintstone && echo 'echo "Welcome, $USER"' > /home/fredflintstone/.bashrc
Обратите внимание на использование &&
, логичный «и», для условного исполнения. Если это , тогда это Анкет
&&
Оператор не следует путать с оператором параллельного исполнения &
отмечено ниже.
Выполнить, если предыдущая команда не удастся: ||
Иногда требуется противоположность вышеизложенного: выполнить следующую команду, если предыдущая Неудача Анкет
Например, возможно, мы хотим добавить DNS -сервер в /etc/resolv.conf
Только если его еще не существует. Мы можем использовать GREP, чтобы проверить, существует ли имя сервера, а затем напишите в файл, если его еще не было:
grep 1.1.1.1 /etc/resolv.conf || echo "nameserver 1.1.1.1" | sudo tee -a /etc/resolv.conf
Обратите внимание на использование , логичный «или», для условного исполнения. Если нет это , тогда это
Также обратите внимание на трубу |
оператор. Это не следует путать с
оператор. Труба
| означает «отправить вывод этой команды на ввод следующего. "В этом случае вывод командных труб
echo .
Логика ветвления с обоими && и ||
Приятная комбинация вышесказанного действительно возможно. Представьте, что вы хотите выполнить команду, тогда, если она удастся, выполните одну команду, но если она не удается, выполните другую команду. Возможна некоторая творческая цепочка, как в этом примере:
id fredflintstone && mkdir -p /home/fredflintstone || id bettyrubble && mkdir /home/bettyrubble
В вышеперечисленном, если одного пользователя не существует, другой будет опробован. Однако следует отметить, что это не эквивалентно оператору if/then/else. Если 2 -я команда mkdir -p/home/fredflintsone
не удастся (маловероятно, с флага -p
), id bettyrubble
все еще будет бежать. Другими словами, при выполнении true && false
Верно
Иногда я использую этот метод, чтобы явно установить человеческие переменные в сценарии, чтобы позже читатели (т. Е. Я) легко поймут, что происходит:
sudo passwd -S $USER && PWD_IS_SET=true || PWD_IS_SET=false
По сути, вышеупомянутые «кэши» — тест, чтобы сценарий мог позже проверить значение $ Pwd_is_set
Много раз, запоминающимся и читаемым способом.
Безоговорочное исполнение с;
Чтобы объединить пару команд вместе в одной строке, используйте полуколон. На человеческом языке полуколон говорит: «Сделай это, подожди, пока он не завершится, а затем сделай это». Например:
echo Hello ; echo World
Исполнение безусловный ; Независимо от того, что делает первая команда, вторая также будет выполнена впоследствии:
cat filename_that_does_not_exist ; echo Continue anyway
Фоновое выполнение с &
Попробуй это:
echo Hello & echo World
Да, обе команды выполнены, но поведение вполне может сильно отличаться от использования ;
выше. Вышеупомянутые две команды были выполнены в параллель Анкет Другими словами, в то же время. Нет никакой гарантии относительно того, что будет завершено первым. На самом деле используя просто &
В конце давней команды позволит ей работать на фоновом режиме на неопределенный срок.
Главный момент в контексте этой статьи: &
не &&
и это не ;
(Порядок и условия для выполнения различны для каждого).
Тестирование тизера
Тщательное исследование команды строительной оболочки тест
Лучше остаться для будущей статьи. Тем не менее, давайте, по крайней мере, немного обрушимся, так как концепция вполне применима к условному выполнению.
Примечание: в Posix -Селкие раковины, такие как Bash, ZSH и Ash/Dash, тест
Команда и [
Команда — та же команда, за исключением, когда [
используется, это должно закончиться ]
Анкет В то время как [
хорошо работает в рисунке, такой как « if [-d some_directory]; затем
» для многострочной читаемости (последняя строка должна быть « fi
», чтобы положить конец утверждению if), для кратких однострочных Я предпочитаю » test -d some_directory
» и тому подобное.
Быстрый чит с некоторыми часто используемыми тестами с использованием тест
Команда:
тест -d some_directory
будет правдой, если существует каталогтест -r some_file
будет правдой, если обычный файл будет читаемымтест -n "$ some_string"
будет правдой, если строка (такая как переменная) не является пустойтест -z "$ some_nonexistent_string"
будет правдой, если строка пуста
Смотрите SPEX SPEC для теста Для многих других вариантов. Вы также можете просмотреть Удовлетворенные выражения или ZSH Условные выражения Для специфических для оболочки документов. Когда это возможно, я стараюсь писать сценарии оболочки в POSIX-совместимых способах переносимости (сценарии, которые работают в различных оболочках).
Выше выше может быть очень полезно для условного исполнения. Что -то подобное работает хорошо:
test -r /etc/resolv.conf || echo "nameserver 1.1.1.1" | sudo tee /etc/resolv.conf
Другими словами, если /etc/resolv.conf
не существует, создайте его с соответствующим содержанием. Но если это уже существует, ничего не делай.
Возможность идентичности (альтернативный заголовок: Поместите немного разработки в свои операции)
Возможно, вы сможете увидеть четкий вариант использования здесь для конфигурации системы. Если вы когда -либо использовали Ansible и аналогичные инструменты конфигурации, вы можете отметить, что желательно, чтобы каждая задача была Idempotent ; Другими словами, даже при запуске более одного раза, желаемый результат одинаков.
Я считаю, что сценарии оболочки были максимально идентифицированными, когда они предназначены для настройки системы в определенном состоянии. Приведенные выше примеры, которые ссылка /etc/resolv.conf
Сделай это хорошо, поэтому я буду ссылаться на них здесь снова:
test -f /etc/resolv.conf || echo "nameserver 1.1.1.1" | sudo tee /etc/resolv.conf grep 1.1.1.1 /etc/resolv.conf || echo "nameserver 1.1.1.1" | sudo tee -a /etc/resolv.conf
Эти две линии очень похожи, и необходим только одна, в зависимости от желаемого результата. Первый — отличный пример создания нового файла с желаемым начальным состоянием. Он использует Тест -f
сначала определить, существует ли файл. Конечно, вы всегда можете перезаписать файл и обеспечить состояние таким образом, но это будет обновлять статистику файла, такую как TimeStamp, без необходимости. Кроме того, этот пример может быть полезен в файлах конфигурации с желаемым начальный Государство, когда ожидаются будущие модификации и не должны быть изменены.
Второе — это пример обеспечения определенного линия существует в файле. Он использует Греп
Чтобы проверить слово или строку в файле, затем добавляет строку тогда и только тогда, когда ее еще нет.
Эти методы достигают Idempothency с комбинацией тестирования и условного исполнения. Достойная цель.
Одностроители и надежные сценарии
Примеры и концепции в этой статье одинаково дома в окне терминала или в существенном сценарии конфигурации. Логика выполнения оболочки должна быть вашим другом. Не стесняйтесь размещать примеры и советы в комментариях ниже.
Оригинал: «https://dev.to/bowmanjd/bash-execution-tips-for-shell-jockeys-and-script-fabricators-5dan»