2016-12-27 57 views
4

有建议使用下面的选项,使猛砸快速失败:猛砸快速失效功能

set -o errexit 
set -o nounset 
set -o pipefail 

这些选项但如预期的Bash函数,通过||管道不起作用。

E.g.在脚本中

#!/bin/bash 

set -o errexit 
set -o nounset 
set -o pipefail 

my_function() { 
    test -z "$1" 
    echo "this SHOULD NOT be printed" 
} 

my_function 1 || echo "???" # 1 

my_function 1 # 2 

echo "this will not be printed" 

# 2将导致脚本以代码1结束而没有任何输出。这是我期望的。

# 1实际上让我困惑:my_function将成功完成,打印“这个不应该被打印”并返回代码0,因此“???”将不会被打印。

如何让Bash在线# 1处理my_function同样失败的快速方式,如在线# 2

+0

只是出于好奇,你在哪里看到这些东西推荐? –

回答

2

望着bash的手册,这里是什么是对trap命令说:

trap [-lp] [arg] [sigspec …]

如果SIGSPEC是ERR,执行命令ARG每当管道(其中可能包括一个单一的简单命令),一个列表或一个复合命令返回一个非零退出状态,受以下条件的影响 。如果失败的命令是命令列表的一部分 紧跟一个直到或不执行ERR陷阱而关键字,以下的测试 部分如果或elif的保留字,在一个& &或执行的 命令的一部分| |除了 最后的& &或||,管道中的最后一个命令,或者命令的返回状态正在使用!!这些与errexit(-e)选项所遵循的条件相同 。

特别看最后一句。这解释了它!

6

也有更好的建议not to use set -e/errexit

显然,我们并不想放弃当条件(在if [ -d /foo ]; then),返回非零。 [...]执行者决定制定一系列特殊规则,比如“作为if测试的一部分的命令是免疫的”,或者“除了最后一条之外的流水线中的命令都是免疫的”。

这些规则是非常复杂的,他们仍然没有抓住甚至一些非常简单的情况。更糟糕的是,这些规则从一个Bash版本转换到另一个版本,因为Bash试图追踪POSIX对这个“特性”的极端滑动定义。当涉及到SubShell时,情况会变得更糟 - 行为会根据是否在POSIX模式下调用Bash而发生变化。

如果脚本是停在非归零,foo || bar也将是无用的,因为bar永远不会运行(该脚本将改为出口)。因此,这些令人费解的规则之一是,在&&||左侧的命令中的非零返回不会导致脚本退出。这是你看到的效果。

没有办法使set -e正常工作,并且没有自动更换。如果不编写手动错误处理,你无法按照你想要的方式工作。