Чому шаблон "команда || справжнє »корисне?


78

Зараз я досліджую пакунки Debian, і читав деякі зразки коду. І в кожному рядку, наприклад, postinstсценарію - це шаблон.

some command || true
another command || true

Отже, якщо якась команда не вдається, то рядок повертає true, але я не бачу, як це впливає на вихід програми.


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

Відповіді:


151

Причиною цього шаблону є те, що сценарії підтримки в пакетах Debian, як правило, починаються з цього set -e, що призводить до того, що оболонка виходить, як тільки будь-яка команда (строго кажучи, конвеєр, список або команда з'єднання) закінчується зі статусом, що не має нуля. Це гарантує, що помилки не накопичуються: як тільки щось піде не так, сценарій припиняється.

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

rmdir ... || true

оскільки rmdirне має можливості сказати це ігнорувати помилки.


4
Ну, set -eа в цьому немає потреби || trueвзагалі, я вважав важливим надати контекст. Якщо ви помітили дивні речі на POWER, я настійно рекомендую вам подавати помилки ( reportbug)!
Стівен Кітт

16
@MichaelFelt, насправді, set -eце не лише "Debian convention", але і хороша схема програмування, яку завжди слід використовувати. Побачити. наприклад, davidpashley.com/articles/writing-robust-shell-scripts
kay

2
на питання тут - чому використовувати || trueset -e - це ймовірний контекст і, ймовірно, найбільш поширений. Я кланяюся цій відповіді! Буквально, однак, корисно в будь-який час стан виходу вважається неактуальним І (як ви додаєте посилання на статтю), я не використовую статус виходу як частина мого контролю сценаріїв. Я бачу утиліту (in set -e), але не пішла б так далеко, як це робиться в статті, і сказати "Кожен написаний сценарій повинен містити set -e вгорі". Це стиль програмування. "ЗАВЖДИ | Кожен" включає в себе власний набір пасток - ака - абсолютний спосіб: рішення диких карт ALWAYSзрештою матимуть зворотну реакцію, так як - немає безкоштовних атракціонів.
Майкл Фельд

1
@Kay Це популярна в даний час перспектива, але в кінцевому рахунку загрожує численними припущеннями, які обмежують портативність сценарію. Існують історичні невідповідності в set -eповедінці. Для вас це може не мати значення, якщо ваші єдині цілі bashта інші відносно недавні снаряди, які живуть /bin/sh, але ситуація стає більш нюансовою, коли ви хочете підтримувати старі оболонки / системи.
mtraceur

2
@StephenKitt Звичайно, річ. Існує дуже ретельна сторінка, яка документує різні set -eповедінки оболонок Свена Маскека , хоча ця сторінка також документує багато історичних / давніх снарядів, які не мають значення сьогодні. Є також ці дві сторінки з більш вузьким сучасним фокусом (пошук "set -e"): сторінка "lintsh" , портативна документація на оболонку autoconf -> Обмеження підсторінки
Builtins

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 ". Швидше за все, у мене є оболонка функція "фатальна", і у мене є "щось || фатальне" мене нещасно ". Імхо сценарій повинен повідомити про невдалий стан, або це не хвилює. -e плюс || true - це маскування помилок. Якщо це те, що я хочу - добре, якщо ні, то я пропускаю помилки
Michael Felt

що я повинен запитати себе: це || true - кодування кодексу (ледачий спосіб обійти / минулу помилку, з якою я не хочу зараз мати справу; інструмент налагодження (-е, але ні || правда) або просто чиясь догма про те, що таке хороша практика кодування. Іншими словами - Я бачу це як особливість - з потенційною вигодою. Я не вважаю це чарівною паличкою, щоб вилікувати все. Словом, так само, як краса в очах глядача - set -eі || trueкорисність визначатиметься рисами та цілями програміст.
Майкл Фетл

6
@MichaelFelt Поміркуйте: git remote remove foo || true git remote add foo http://blah- ми хочемо ігнорувати помилку, якщо пульт відсутній.
іммібіс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.