微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何检测bash中的“无法分叉”错误?

如何解决如何检测bash中的“无法分叉”错误?

由于当前未知的原因,我们的其中一个bash脚本在运行以下简单行时会产生“无法分叉”错误

myvar=`mycmd || echo "error"; exit 2`

显然,问题在于无法创建(派生)新进程,因此该命令失败。

但是bash只会忽略该错误并继续在脚本中运行,从而导致意外的问题。

如您所见,我们已经检查了命令本身是否存在错误,但是甚至在命令运行之前就出现了“ Cannot fork”错误

有没有办法捕获该错误并阻止bash执行?

解决方法

此错误检查实际上存在几个问题,这将阻止它正确处理任何错误,而不仅仅是“无法分叉”错误。

第一个问题是||的优先级高于;,因此mycmd || echo "error"; exit 2仅在echo "error"失败的情况下才能运行mycmd,但它将运行exit 2 无条件,无论mycmd是成功还是失败。

为了解决此问题,应将错误处理命令与{ }组合在一起。类似于:mycmd || { echo "error"; exit 2; }。请注意,必须在;之前插入}或换行符,否则}将被视为exit的参数。

(顺便说一句,有时我会简称为mycmd || echo "error" && exit 2。请不要这样做。如果echo由于某种奇怪的原因而失败,则它将不会运行exit。)

所有这些echoexit,都在反引号创建的子外壳中运行(或者如果该子外壳已成功分叉,则将在子外壳中运行)。这意味着错误消息将保存在myvar中,而不是打印出来(错误消息通常应发送到标准错误,例如echo "error" >&2);更重要的是,将退出的子外壳,而不是运行脚本的外壳。主脚本将注意到该子shell退出并出现错误...,并且一直保持运行状态。 (好吧,除非您设置了-e,但这是whole other ball of potential bugs。)

解决方案是将||东西放在 后的反引号(或`$(,因为通常比反引号更可取))。这样,它就发生在主外壳中,即打印出错误,即出现错误时退出,等等。这也应解决“无法分叉”的问题,尽管我尚未对其进行测试。

因此,通过所有这些更正,它应该看起来像这样:

myvar=$(mycmd) || {
    echo "error" >&2
    exit 2
}

哦,正如查尔斯·达菲(Charles Duffy)在评论中指出的那样,如果您使用local myvar=$(mycmd)export myvar=$(mycmd)之类的内容,则local / export /任何命令都将覆盖从mycmd退出状态。如果需要这样做,请将变量的属性与其值分开设置:

local myvar
myvar=$(mycmd) || {
...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。