为什么使用Bash只读变量来捕获输出无法捕获返回码$?

Vin*_*gis 12 variables bash

这是一个尝试执行命令并检查它是否成功执行的示例,同时捕获它的输出以进行进一步处理:

#!/bin/bash

readonly OUTPUT=$(foo)
readonly RES=$?

if [[ ${RES} != 0 ]]
then
    echo "failed to execute foo"
    exit 1
else
    echo "foo success: '${OUTPUT}'"
fi
Run Code Online (Sandbox Code Playgroud)

它报告它是成功的,即使没有这样的foo可执行文件.但是,如果我readonlyOUTPUT变量中删除,它会保留错误的退出代码并检测到故障.

我尝试使用readonly作为"防御性编程"技术,如某处所推荐的那样......但在这种情况下看起来像是咬了自己.

是否有一些干净的解决方案,以保持readonly仍然捕获命令/子shell的退出代码?令人失望的是,人们必须记住这种特殊的用例,或者恢复到不使用readonly永远......

在Debian Wheezy上使用Bash 4.2.37(1).

Joh*_*024 12

问题是readonly它自己的命令和它返回的退出代码是它自己的退出代码,而不是命令替换的退出代码.

来自help readonly:

退出状态:
除非给出无效选项或NAME无效,否则返回成功.

因此,您需要使用两个单独的命令:

$ output=$(false)
$ readonly res=$?
$ readonly output
Run Code Online (Sandbox Code Playgroud)

这将保存您想要的退出代码:

$ echo $res
1
Run Code Online (Sandbox Code Playgroud)

短期的进入调试器,没有办法取消设置只读变量.因此,除非您希望它在剩余的bash会话中保持不变,否则不要设置readonly变量.

变异

这两个readonly命令可以组合成一个(帽子提示:Chepner):

$ output=$(false)
$ readonly output res=$?
$ echo $res
1
Run Code Online (Sandbox Code Playgroud)

在旁边

最好的做法是为变量使用低位或混合大小写的名称.系统使用所有大写名称,您不希望意外覆盖系统变量.