gpt4 book ai didi

linux - 为什么在复合命令 w/|| 中调用该函数时函数中 set -e 的行为会发生变化或者 &&?

转载 作者:太空宇宙 更新时间:2023-11-04 09:20:28 25 4
gpt4 key购买 nike

我将我的问题缩小到一个让我困惑的简单例子。

我已经在 Centos 上使用 GNU bash 4.2.46 和在 Ubuntu 上使用 4.3.46 对其进行了测试。

这是一个 bash 函数,它在单独调用时返回非零(错误)返回码,但在我使用 && 或 || 时反转它的行为链接另一个命令。对我来说它看起来像一个错误。有人可以解释为什么它会这样吗?

$ echo $0
/bin/bash
$ function TEST() {( set -e; set -o pipefail; echo OK; false; echo NOT REACHED; )}
$ type TEST
TEST is a function
TEST ()
{
( set -e;
set -o pipefail;
echo OK;
false;
echo NOT REACHED )
}
$ TEST
OK
$ echo $?
1
$ TEST || echo "NON ZERO"
OK
NOT REACHED
$ echo $?
0
$ TEST && echo "UNEXPECTED"
OK
NOT REACHED
UNEXPECTED
$ echo $?
0

最佳答案

您看到的是 shell 正在执行指定的操作。 if 语句和循环中的非零返回码和 || && 逻辑运算符不会触发 set -e< 的检测 或陷阱。这使得严重错误处理比其他语言更加困难。

所有问题的根源在于,在 shell 中,返回一个非零代码作为有意义和预期的状态,或者作为命令以不受控制的方式失败的结果没有区别。此外,shell 具有的特殊情况将禁用调用堆栈中所有深度的检查,而不仅仅是第一个,完全隐藏 set -e 和陷阱的嵌套失败(如果你问我,这是纯粹的邪恶).

这里有一个简短的例子来说明我的意思。

#!/bin/bash

nested_function()
{
returnn 0 ; # Voluntarily misspelled
}

test_function()
{
if
[[ some_test ]]
then
nested_function
else
return 1
fi
}

set -e
trap 'echo Will never be called' ERR

if
test_function
then
echo "Test OK"
else
echo "Test failed"
fi

第一个函数有一个明显的错误。此函数不包含任何禁用错误检查的内容,但由于它嵌套在 if block 中(请注意,甚至不是直接嵌套),该错误将被完全忽略。

你在 Java 中没有这个问题,返回值是一回事,异常是另一回事,在 if 语句中评估返回值不会阻止调用堆栈中任何级别的异常都无法完成其工作。您有 try/catch 来处理异常,并且没有办法将异常与返回码混合使用,它们是根本不同的东西(异常可以用作返回值,但不会触发异常机制)就像抛出时一样)。

如果你想在 shell 编程中拥有相同的东西,你必须自己构建它。它可以使用一个“try”函数来完成,该函数在所有调用之前使用并为每个嵌套调用保持状态,一个“throw”等价物允许抛出异常(不是非零返回码,而是存储在变量中), 和 trap ... ERR 来拦截非零返回码并能够执行诸如生成堆栈跟踪和触发受控退出之类的事情(例如删除临时文件、释放其他资源、执行通知) ).

使用这种方法,“异常”是明确处理的失败,非零返回码是错误。我猜你会牺牲一点性能,实现起来并不简单,而且需要大量的纪律。就调试的简易性和复杂性而言,您可以在脚本中构建而不会在尝试追踪问题根源时不知所措,但它改变了游戏规则。

关于linux - 为什么在复合命令 w/|| 中调用该函数时函数中 set -e 的行为会发生变化或者 &&?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42519169/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com