[Перевод] ${var?} и && — два простых помощника в работе с командами оболочки из документации

gc2nq-ria_lilrvjeo8wgfleno0.png

tl; dr: используйте инструкцию ${placeholders?} для выдачи ошибки при пропуске параметра и объединяйте команды оболочки с помощью &&, чтобы упростить и обезопасить их копирование из технической документации.

Я часто обращаюсь к документации, откуда копирую команды оболочки. К примеру, для установки JDK это может выглядеть так:

sudo apt-get update
sudo apt-get install openjdk--jdk

Очевидно, что этот пример прост и понятен. Более реалистичный же случай может содержать команды из 160+ символов, вызывающие незнакомые инструменты и скрипты утилит со множеством фиксированных и переменных параметров. Многие подобные примеры вы без проблем найдете во внутренней технической документации вашей компании.

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

Используйте ${NAME?} вместо специальных плейсхолдеров вроде NAME или 


Если я случайно упущу одни из плейсхолдеров там, где нужно что-либо вставить, этот POSIX-совместимый синтаксис «ошибка-при-пропуске» приведет к провалу команды и выводу четкого сообщения:
$ sudo apt-get install openjdk-${VERSION?}-jdk
bash: VERSION: parameter not set

(Это будет работать при условии отсутствия переменной среды с тем же именем).

Сравните предложенный вариант с оригинальными угловыми скобками, которые в лучшем случае дадут сбой с неверным указанием ошибки:

$ sudo apt-get install openjdk--jdk
bash: VERSION: No such file or directory

Или приведут к созданию/усечению файлов, давая сбивающие с толку ошибки (если вообще повезет их получить):
$ sudo apt-get install openjdk--jdk
E: Unable to locate package openjdk
$ grep VERSION *
grep: invalid option -- 'j'

Здесь перенаправление >-jdk было интерпретировано как перенаправление файла (также как в echo Hi > foo.txt). В результате был создан файл -jdk, что привело к неожиданному сбою корректных команд с globs (а представьте, что бы произошло с grep ~/.bashrc!).

Для слова в верхнем регистре может быть трудно различить, является ли оно чем-то вроде ID, частью команды или плейсхолдером. Оболочка же попытается выполнить команду независимо от правильности моего предположения.

Используйте && между последовательными командами


Использование && для объединения нескольких последовательных команд дает даже не одно, а два преимущества:
sudo apt-get update &&
sudo apt-get install openjdk-${VERSION?}-jdk

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

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

$ sudo apt-get update
[sudo] password for vidar:
Sorry, try again.
[sudo] password for vidar:

Я вставил две команды, но первой требуется пароль. Далее в качестве пароля была считана вторая команда, что привело к ошибке "Sorry, try again".

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

Сравните этот вариант с использованием &&, когда оболочка терпеливо считывает все команды заранее (за счет указателя на продолжение >) и только затем начинает их выполнять:

$ sudo apt-get update &&
> sudo apt-get install openjdk-14-jdk
[sudo] password for vidar:

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

Заключение


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

oug5kh6sjydt9llengsiebnp40w.png

© Habrahabr.ru