Почему шаблон «команда || правда »полезно?

79

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

some command || true
another command || true

Так что, если какая-то команда завершится неудачно, строка вернет true, но я не вижу, как это повлияет на вывод программы.

столяр
источник
5
К вашему сведению, ||:это еще один идиоматический способ написания этого ( :будучи еще одной записью во встроенной таблице, указывающей на true- но гарантированно встроенной даже в Борне; при этом для POSIX sh trueтакже гарантированно будет встроенной - так что это больше краткости, чем эффективности в даже отдаленно-современные времена).
Чарльз Даффи

Ответы:

151

Причина этого шаблона заключается в том, что сценарии сопровождающего в пакетах Debian, как правило, начинаются с того set -e, что оболочка завершает работу, как только завершается любая команда (строго говоря, команда pipe, list или составная команда) с ненулевым статусом. Это гарантирует, что ошибки не будут накапливаться: как только что-то пойдет не так, скрипт прерывается.

В тех случаях, когда команде в сценарии разрешается сбой, добавление || trueгарантирует, что результирующая составная команда всегда завершается с нулевым статусом, поэтому сценарий не прерывается. Например, удаление каталога не должно быть фатальной ошибкой (предотвращение удаления пакета); поэтому мы будем использовать

rmdir ... || true

так rmdirкак не имеет возможности сказать ему игнорировать ошибки.

Стивен Китт
источник
4
Ну, без set -eнужды || trueвообще я думал, что важно предоставить контекст. Если вы заметили странные вещи на POWER, я настоятельно рекомендую вам регистрировать ошибки ( reportbug)!
Стивен Китт
16
@MichaelFelt, на самом деле set -eэто не только «соглашение Debian», но и хороший шаблон программирования, который всегда следует использовать. Видеть. например, davidpashley.com/articles/writing-robust-shell-scripts
кей
2
на вопрос здесь - почему использование || trueset -e является вероятным контекстом и, вероятно, наиболее распространенным. Я преклоняюсь перед этим ответом! Буквально, однако, это полезно в любое время, когда статус выхода считается неактуальным И (как добавляет ссылка на вашу статью) Я не использую статус выхода как часть контроля скрипта. Я вижу утилиту (in set -e), но не буду заходить так далеко, как в статье, и скажу: «Каждый сценарий, который вы пишете, должен включать -e вверху». Это стиль программирования. «ВСЕГДА | Каждый» включает в себя свой собственный набор ловушек - иначе - абсолюты: решения с ALWAYSподстановочными знаками в конечном итоге будут иметь обратный эффект, иначе - никаких бесплатных поездок.
Майкл чувствовал себя
1
@Kay Это популярная в настоящее время перспектива, но в конечном итоге она связана с многочисленными допущениями, которые ограничивают переносимость скрипта. Есть исторические несоответствия с set -eповедением. Для вас может не иметь значения, если ваши единственные цели - это bashи другие относительно недавние оболочки, которые живут /bin/sh, но ситуация более нюансирована, если вы хотите поддерживать старые оболочки / системы.
mtraceur
2
@StephenKitt Конечно. Существует очень тщательная страница, в которой документировано set -eповедение различных оболочек Свена Машека , хотя эта страница также документирует множество исторических / древних оболочек, не относящихся к сегодняшнему дню . Есть также эти две страницы с более узким современным фокусом (поиск «set -e»): страница «lintsh» , документация переносимой оболочки autoconf -> Подстраница «Ограничение встроенных функций»
mtraceur
32

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

Перефразировано: маскирует статус ошибки предыдущей команды.

michael@x071:[/usr/sbin]cat /tmp/false.sh
#!/bin/sh
false

michael@x071:[/usr/sbin]cat /tmp/true.sh 
#!/bin/sh
false || true

michael@x071:[/usr/sbin]sh /tmp/false.sh; echo $?
1
michael@x071:[/usr/sbin]sh /tmp/true.sh; echo $? 
0
Майкл Фетт
источник
6
Это правда, но это не отвечает, почему маскировка статуса завершения команды полезна.
moopet
4
set -e означает, что скрипт будет немедленно завершен при ненулевом возврате. Вы можете в этом локализованном месте не хотеть, чтобы это произошло!
rackandboneman
Я простой человек - и для меня единственная причина маскировать статус ошибки, потому что она «в пути». set -e делает любую ошибку "в пути", если раньше вам было все равно. Мне нравится обсуждение, потому что я вижу, что это хороший способ помочь мне отладить мои сценарии и написать дополнительную логику для ответа на ошибку (например, || print - «xxx существовал ненулевой здесь». Скорее всего, у меня есть функция оболочки 'роковая', и у меня есть "что-то || фатальное" несчастное меня ". imho скрипт должен сообщать о сбойном состоянии или не заботиться. -e плюс || true - это маскирование ошибок. если нет, я пропускаю ошибки
Майкл Фетт
я должен спросить себя: true - костыль кодирования (ленивый способ обойти / пропустить ошибку, с которой я сейчас не хочу иметь дело; инструмент отладки (-e, но не || true) или просто чья-то догма о том, что такое хорошая практика кодирования. Другими словами - Я рассматриваю это как особенность - с потенциальной выгодой. Я не рассматриваю это как волшебную палочку, чтобы вылечить всех. Короче говоря - как красота в глазах смотрящего - set -eи || trueполезность будет определяться чертами и целями программист.
Майкл чувствовал себя
6
@MichaelFelt Подумайте: git remote remove foo || true git remote add foo http://blah- мы хотим игнорировать ошибку, если пульт не существует.
user253751 25.11.16