Этот вопрос появился в викторине перед собеседованием, и это сводит меня с ума. Кто-нибудь может ответить на это и успокоить меня? Тест не имеет ссылки на конкретную оболочку, но описание задания предназначено для Unix Sa. опять вопрос просто ...
Что делает 'set -e', и почему это может считаться опасным?
Ответы:
set -e
заставляет оболочку завершиться, если какая-либо подкоманда или конвейер возвращает ненулевой статус.Ответ, который интервьюер, вероятно, искал:
С http://www.debian.org/doc/debian-policy/ch-opersys.html 9.3.2 -
Это правильный вопрос с точки зрения интервьюера, потому что он оценивает кандидатов, обладающих знаниями в области написания сценариев и автоматизации на уровне сервера.
источник
От
bash(1)
:К сожалению, я не достаточно изобретателен, чтобы думать о том, почему это было бы опасно, кроме того, что «остальная часть сценария не будет выполнена» или «возможно, это может маскировать реальные проблемы».
источник
set
! Я всегда заканчиваю вbuiltin(1)
. Благодарю.set
Откуда мне знать, что документация должна быть найдена вman 1 bash
?? и как кто-нибудь сможет найти-e
опцию дляset
ключевого слова на странице руководства, которая так огромна? Вы не можете просто/-e
искать здесьhelp set
Следует отметить, что
set -e
можно включать и выключать различные разделы скрипта. Это не должно быть включено для выполнения всего сценария. Это может быть даже условно включено. Тем не менее, я никогда не использую его, так как я делаю свою собственную обработку ошибок (или нет).Также следует обратить внимание на раздел справочной страницы Bash
trap
команды, в котором также описывается, какset -e
функционирует при определенных обстоятельствах.Таким образом, существуют некоторые условия, при которых ненулевой статус не приведет к выходу.
Я думаю, что опасность состоит в том, что мы не понимаем, когда
set -e
вступает в игру, а когда нет, и неправильно полагаются на это в соответствии с каким-то неверным предположением.См. Также BashFAQ / 105. Почему set -e (или set -o errexit, или trap ERR) не выполняет то, что я ожидал?
источник
Имейте в виду, что это викторина для собеседования. Вопросы могут быть написаны нынешним персоналом, и они могут быть неправильными. Это не обязательно плохо, и все делают ошибки, и вопросы интервью часто остаются в темном углу без обзора и выходят только во время интервью.
Вполне возможно, что set -e ничего не делает, что мы считаем «опасным». Но автор этого вопроса может ошибочно полагать, что «set -e» опасно из-за собственного невежества или предвзятости. Может быть, они написали глючный сценарий оболочки, он ужасно бомбил, и они ошибочно полагали, что виноват 'set -e', хотя на самом деле они пренебрегали написанием надлежащей проверки ошибок.
Я принимал участие, вероятно, в 40 собеседованиях за последние 2 года, и интервьюеры иногда задают вопросы, которые являются неправильными или имеют неправильные ответы.
Или, может быть, это вопрос с подвохом, который был бы неубедительным, но не совсем неожиданным.
Или, может быть, это хорошее объяснение: http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg473314.html
источник
set -e
говорит bash, в скрипте, что выходить всякий раз, когда что-либо возвращает ненулевое возвращаемое значение.я мог видеть, как это будет раздражать и глючить, не уверен в том, что это опасно, если только вы не открыли разрешения для чего-либо, и, прежде чем вы смогли снова их ограничить, ваш сценарий умер.
источник
set -e
, по сути, для меня это говорит о лени игнорировать проверку ошибок в ваших скриптах ... так что имейте это в виду, с этим работодателем тоже ... если они его используют много, как выглядят их сценарии, которые вам неизбежно придется поддерживать ...set -e
завершает сценарий, если встречается ненулевой код выхода, кроме как при определенных условиях. Кратко говоря об опасности его использования: оно не ведет себя так, как думают люди.На мой взгляд, это следует рассматривать как опасный хак, который продолжает существовать только в целях совместимости. Оператор
set -e
не превращает оболочку из языка, использующего коды ошибок, в язык, использующий поток управления, подобный исключению, он просто слабо пытается эмулировать это поведение.Грег Вулледж может многое сказать об опасностях
set -e
:set -e
)Во второй ссылке есть различные примеры неинтуитивного и непредсказуемого поведения
set -e
.Некоторые примеры не интуитивного поведения
set -e
(некоторые взяты из вики-ссылки выше):let x++
возвращает 0, которое рассматриваетсяlet
ключевым словом как ложное значение и превращается в ненулевой код завершения.set -e
замечает это и молча завершает сценарий.Вышеуказанное работает как положено, выводит предупреждение, если оно
/opt/foo
уже существует.Вышеупомянутое, несмотря на то, что единственная строка была преобразована в функцию, прекратит работу, если
/opt/foo
ее не существует. Это потому, что тот факт, что он работал изначально, является особым исключением изset -e
поведения России. Когдаa && b
возвращается ненулевое значение, оно игнорируетсяset -e
. Однако теперь, когда это функция, код выхода функции равен коду выхода этой команды, и функция, возвращающая ненулевое значение, автоматически завершит выполнение сценария.Выше будет читать массив
config_vars
из файлаconfig
. Как мог бы предположить автор, он завершается с ошибкой, еслиconfig
отсутствует. Поскольку автор, возможно, не намерен, он молча завершается, еслиconfig
не заканчивается новой строкой. Если быset -e
они здесь не использовались, тоconfig_vars
содержали бы все строки файла независимо от того, заканчивался ли он новой строкой.Пользователи Sublime Text (и других текстовых редакторов, которые неправильно обрабатывают переводы строк), остерегаются.
Автор здесь может разумно ожидать, что если по какой-то причине пользователь
$user
не существует, тоgroups
команда завершится неудачно, и сценарий завершится, вместо того, чтобы позволить пользователю выполнить некоторую задачу без проверки. Однако в этом случаеset -e
прекращение никогда не вступает в силу. Если$user
по какой-либо причине не может быть найдено, вместо завершения сценарияshould_audit_user
функция просто вернет неверные данные, как если бы ониset -e
не действовали.Это относится к любой функции, вызываемой из условной части
if
инструкции, независимо от того, насколько глубоко она вложена, где бы она ни была определена, даже если выset -e
снова запускаете ее внутри. Использованиеif
в любой точке полностью отключает эффектset -e
до тех пор, пока блок условий не будет полностью выполнен. Если автор не знает об этой ловушке или не знает весь свой стек вызовов во всех возможных ситуациях, когда функция может быть вызвана, тогда он напишет ошибочный код, и ложное чувство безопасности, обеспечиваемое,set -e
будет, по крайней мере, частично виноваты.Даже если автор полностью осознает эту ловушку, обходной путь состоит в том, чтобы писать код так же, как если бы он был написан без него
set -e
, эффективно делая этот переход менее чем бесполезным; Мало того, что автор должен написать код обработки ошибок вручную, как если бы онset -e
не был в силе, но и наличиеset -e
могло ввести их в заблуждение, заставляя их думать, что они не обязаны это делать.Некоторые дополнительные недостатки
set -e
:let x++
приведенным выше, это не так. Если сценарий неожиданно умирает, он обычно молча, что затрудняет отладку. Если сценарий не умер, и вы ожидали его (см. Предыдущий пункт), то у вас в руках более тонкий и коварный баг.if
точку пули -условия.set -e
что он был настроен между этими версиями.set -e
Это спорный вопрос, и некоторые люди, знающие о проблемах вокруг него, рекомендуют против него, в то время как другие просто рекомендуют позаботиться, пока он активен, чтобы знать подводные камни. Есть много новичков в написании сценариев оболочки, которые рекомендуютset -e
все сценарии как универсальное средство для выявления ошибок, но в реальной жизни это не работает.set -e
не заменит образование.источник
Я бы сказал, что это опасно, потому что ты больше не контролируешь его поток сценариев. Сценарий может завершиться, пока любая из команд, которые вызывает сценарий, возвращает ненулевое значение. Поэтому все, что вам нужно сделать, это сделать что-то, что изменит поведение или вывод любого из компонентов, и вы получите возможность завершить основной сценарий. Это может быть больше проблема стиля, но это определенно имеет последствия. Что если ваш основной сценарий должен установить какой-либо флаг, а он этого не сделал, потому что завершился рано? В конечном итоге вы выйдете из строя с остальной системой, если она предполагает, что флаг должен быть там, или работает с неожиданным значением по умолчанию или старым значением.
источник
В качестве более конкретного примера ответа @ Marcin, который лично меня укусил, представьте, что
rm foo/bar.txt
где-то в вашем сценарии есть строчка. Обычно нет ничего сложного, если наfoo/bar.txt
самом деле не существует. Однако сset -e
настоящим моментом ваш сценарий завершится там рано! К сожалению.источник