Answers:
set -e
如果任何子命令或管道返回非零状态,将导致外壳退出。
面试官可能正在寻找的答案是:
创建init.d脚本时使用“ set -e”是危险的:
从http://www.debian.org/doc/debian-policy/ch-opersys.html 9.3.2-
注意在init.d脚本中使用set -e。编写正确的init.d脚本要求在守护程序已经运行或已经停止时接受各种错误退出状态,而不会中止init.d脚本,并且使用set -e进行调用时,通常的init.d函数库并不安全。对于init.d脚本,不使用set -e而不是分别检查每个命令的结果通常会更容易。
从面试官的角度来看,这是一个有效的问题,因为它可以评估应聘者在服务器级脚本和自动化方面的工作知识
来自bash(1)
:
-e Exit immediately if a pipeline (which may consist of a
single simple command), a subshell command enclosed in
parentheses, or one of the commands executed as part of
a command list enclosed by braces (see SHELL GRAMMAR
above) exits with a non-zero status. The shell does not
exit if the command that fails is part of the command
list immediately following a while or until keyword,
part of the test following the if or elif reserved
words, part of any command executed in a && or ││ list
except the command following the final && or ││, any
command in a pipeline but the last, or if the command’s
return value is being inverted with !. A trap on ERR,
if set, is executed before the shell exits. This option
applies to the shell environment and each subshell envi-
ronment separately (see COMMAND EXECUTION ENVIRONMENT
above), and may cause subshells to exit before executing
all the commands in the subshell.
不幸的是,除了“脚本的其余部分将无法执行”或“它可能掩盖实际问题”之外,我没有足够的创意去思考为什么这样做会很危险。
set
!我总是以builtin(1)
。谢谢。
set
将在man 1 bash
?? 中找到?以及如何在巨大的手册页中找到该关键字的-e
选项set
?您不能只/-e
在这里搜索
help set
应当注意,set -e
可以为脚本的各个部分打开和关闭。整个脚本的执行不必一定要启用。甚至可以有条件地启用它。就是说,我从来没有使用过它,因为我自己进行错误处理(或不进行错误处理)。
some code
set -e # same as set -o errexit
more code # exit on non-zero status
set +e # same as set +o errexit
more code # no exit on non-zero status
同样值得注意的是该trap
命令的Bash手册页部分,该部分还描述了set -e
在某些情况下的功能。
如果失败的命令是紧随while或直到关键字之后的命令列表的一部分,if语句中的测试的一部分,在&&或⎪⎪列表中执行的命令的一部分,或者命令的命令的一部分,则不执行ERR陷阱。返回值通过!反转。这些是errexit选项遵循的相同条件。
因此,在某些情况下,非零状态不会导致退出。
我认为危险在于不了解何时set -e
发挥作用以及何时不发挥作用,并且在某些无效的假设下错误地依赖它。
请记住,这是求职面试的一项测验。这些问题可能是当前员工写的,可能是错误的。这并不一定是坏事,每个人都会犯错,面试问题通常位于一个黑暗的角落,没有经过审查,只有在面试时才会出现。
“ set -e”完全没有做任何我们认为“危险”的事情。但是,该问题的作者可能会误认为“ set -e”是危险的,因为他们自己的无知或偏见。也许他们编写了一个有问题的shell脚本,遭到了轰炸,然后他们错误地认为是“ set -e”的罪魁祸首,而实际上他们却忽略了编写适当的错误检查程序。
在过去的两年中,我大概参加了40次面试,而面试官有时会提出错误的问题,或者给出错误的答案。
也许这是一个棘手的问题,这很la脚,但并非完全出乎意料。
也许这是一个很好的解释:http : //www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg473314.html
set -e
告诉bash在脚本中任何东西返回非零返回值时退出。
我可以看到这将是多么烦人和麻烦,不确定危险性,除非您已对某些内容开放了权限,并且在可以再次限制它们之前,您的脚本已经死了。
set -e
,实际上,对我而言,它懒惰地忽略了脚本中的错误检查...因此,请与该雇主一起记住这一点...如果他们使用它很多情况下,它们的脚本是什么样的,您将不可避免地需要维护...
set -e
如果遇到非零退出代码,则在某些情况下终止脚本。用几句话总结使用它的危险:它没有表现出人们认为的行为。
在我看来,应该将其视为危险的hack,仅出于兼容性目的而继续存在。该set -e
语句不会将Shell从使用错误代码的语言转换为使用类似异常控制流的语言,而只是在尝试模仿这种行为时进行了错误的尝试。
Greg Wooledge对于以下危险有很多话要说set -e
:
set -e
)在第二个链接中,存在有关的直观和不可预测行为的各种示例set -e
。
以下是一些不直观行为的示例set -e
(某些摘自上面的Wiki链接):
设置-e x = 0 让x ++ 回声“ x是$ x”上面的代码将导致Shell脚本过早退出,因为
let x++
返回0,该值被let
关键字视为虚假值并转换为非零退出代码。set -e
注意到这一点,并以静默方式终止脚本。设置-e [-d / opt / foo] && echo“警告:已经安装foo。将覆盖。” >&2 回声“正在安装foo ...”
上面的方法按预期工作,如果/opt/foo
已经存在,则打印警告。
设置-e check_previous_install(){ [-d / opt / foo] && echo“警告:已经安装foo。将覆盖。” >&2 } check_previous_install 回声“正在安装foo ...”
尽管唯一的区别是单行已重构为函数,但以上内容将终止(如果/opt/foo
不存在)。这是因为它本来可以工作的事实是set -e
行为的特殊例外。当a && b
返回非零值时,它将被忽略set -e
。但是,既然它是一个函数,则该函数的退出代码等于该命令的退出代码,并且返回非零的函数将以静默方式终止脚本。
设置-e IFS = $'\ n'读取-d''-r -a config_vars <config
上面将从config_vars
文件中读取数组config
。正如作者可能打算的那样,如果config
丢失,它将以错误终止。正如作者可能不希望的那样,如果config
不以换行符结尾,则它默默终止。如果set -e
此处未使用,则config_vars
它将包含文件的所有行,无论文件是否以换行符结尾。
Sublime Text(以及其他错误处理换行符的文本编辑器)的用户要当心。
设置-e should_audit_user(){ 本地组groups =“ $(组” $ 1“)” 用于$ groups中的组;做 如果[“ $ group” =审计]; 然后返回0; 科幻 完成 返回1 } 如果should_audit_user“ $ user”; 然后 记录器'Blah' 科幻
此处的作者可能会合理地期望,如果由于某种原因该用户$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
-condition项目符号点。set -e
之间进行了调整,因此可能意外地编写了在较旧版本的bash上表现不同的脚本。set -e
这是一个有争议的问题,一些意识到它周围问题的人建议反对它,而另一些人则建议在它主动知道陷阱时小心谨慎。有许多shell脚本新手推荐set -e
所有脚本作为错误条件的综合解决方案,但在现实生活中,这样做并非如此。
set -e
不能替代教育。
我想说这很危险,因为您不再控制他的脚本流动了。只要脚本调用的任何命令返回非零值,脚本就可以终止。因此,您要做的就是做一些改变任何组件的行为或输出的操作,然后终止主脚本。这可能更多是样式问题,但肯定会带来后果。如果您的主脚本应该设置一些标志,但不是因为它提前终止,该怎么办?如果它假定该标志应该存在,或者使用一个意外的默认值或旧值,您最终都会对系统的其余部分造成错误。