如何将Bash中的local与set -o errexit结合使用?

时间:2015-12-23 21:26:10

标签: bash error-handling

我是Bash的新手,我很难弄清楚为什么当我使用set -o errexit并且命令失败时,脚本没有退出。

似乎是因为我宣布了一个局部变量!

请告诉我如何同时使用局部变量和设置-o errexit。

示例:

#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail

function test {
 local output=$(ls --badoption)
 echo "error code is $?"
 echo "output=$output"
}

test

结果:

./test.sh
ls: illegal option -- -
usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]
error code is 0
output=

可是:

#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail

function test {
 output=$(ls --badoption)
 echo "error code is $?"
 echo "output=$output"
}

test

结果:

ls: illegal option -- -
usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]

2 个答案:

答案 0 :(得分:4)

这是因为set -o errexit(或使用-e运行bash)仅影响简单命令(如bash手册页中所定义)。 cmd中的local output=$(cmd)不被视为简单命令,因此-e没有任何影响($?cmd没有任何关系退出)。一个简单的解决方法是通过替换:

来拆分该行
local output=$(ls --badoption)

使用:

local output

output=$(ls --badoption)

在我的测试中执行您想要的所有内容,它会立即退出,如果您将ls --badoption替换为ls,则可以正常工作,并在调用{{1}之前设置output然后在显示test之后回显它output确实是test的本地。

答案 1 :(得分:2)

local的文档说:

  

返回状态为零,除非在函数外部使用local,提供了无效的名称,或者name是只读变量。

因此local命令的返回状态不受命令替换中执行的命令是否成功的影响。

正如他的回答中指出的那样,你可以通过分离声明和局部变量的赋值来获得你想要的效果。使用命令替换的普通赋值的返回状态是执行命令的子shell的返回状态。