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

用户327407

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

我已经在 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
弗雷德

您所看到的是外壳正在执行指定的操作。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块中(注意,甚至不是直接嵌套),该错误将被完全忽略。

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

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

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么在Java中调用setTimeout函数之前,我的值会发生变化?

来自分类Dev

使用片段更改为横向时,地图行为会发生变化

来自分类Dev

使用片段更改为横向时,地图行为会发生变化

来自分类Dev

通过JNI在Java代码中运行EGL函数时,为什么我对EGL函数的调用会发生变化?

来自分类Dev

为什么[0]会发生变化?

来自分类Dev

堆栈中的代码本身会发生变化

来自分类Dev

使用Numpy Convolve时振幅会发生变化

来自分类Dev

从函数返回时,为什么矢量内部的指针会发生变化?

来自分类Dev

当在强度上绘制时,颤动图发生变化

来自分类Dev

传递给c ++中的函数后,整数变量的值会发生变化

来自分类Dev

为什么HashSet的keySet中的元素顺序在运行之间会发生变化?

来自分类Dev

为什么表达式类型在C ++中的版本之间会发生变化?

来自分类Dev

为什么Excel中的图形在输入日期后会发生变化?

来自分类Dev

为什么宽度属性在更改 html 中的填充属性时会发生变化

来自分类Dev

为什么在 tensorflow 会话中访问 keras 模型参数值会发生变化?

来自分类Dev

为什么在 Google Play API 中取消订阅后到期会发生变化?

来自分类Dev

为什么在调用pop()之后top()的返回值会发生变化?

来自分类Dev

为什么在 JSON.parse 调用后整数值会发生变化

来自分类Dev

在什么情况下,azure 函数的授权密钥会发生变化?

来自分类Dev

为什么在Webkit过滤器悬停时堆叠顺序会发生变化?

来自分类Dev

为什么追加熊猫数据框时列顺序会发生变化?

来自分类Dev

为什么玩家落在平台上时平台的速度会发生变化?

来自分类Dev

为什么我移动时游戏中的事物会发生变化?Java处理环境

来自分类Dev

为什么从左向右滚动时ui-grid的高度会发生变化?

来自分类Dev

Python:为什么在使用 for 循环 for with float() 时每个元素的位置会发生变化

来自分类Dev

为什么更改新列表时原始列表会发生变化?

来自分类Dev

为什么包含选项卡时 printf 数字的结果会发生变化?

来自分类Dev

为什么克隆时原始 django 对象会发生变化?

来自分类Dev

Flask:为什么定义变量时 ajax 数据的内容会发生变化?

Related 相关文章

  1. 1

    为什么在Java中调用setTimeout函数之前,我的值会发生变化?

  2. 2

    使用片段更改为横向时,地图行为会发生变化

  3. 3

    使用片段更改为横向时,地图行为会发生变化

  4. 4

    通过JNI在Java代码中运行EGL函数时,为什么我对EGL函数的调用会发生变化?

  5. 5

    为什么[0]会发生变化?

  6. 6

    堆栈中的代码本身会发生变化

  7. 7

    使用Numpy Convolve时振幅会发生变化

  8. 8

    从函数返回时,为什么矢量内部的指针会发生变化?

  9. 9

    当在强度上绘制时,颤动图发生变化

  10. 10

    传递给c ++中的函数后,整数变量的值会发生变化

  11. 11

    为什么HashSet的keySet中的元素顺序在运行之间会发生变化?

  12. 12

    为什么表达式类型在C ++中的版本之间会发生变化?

  13. 13

    为什么Excel中的图形在输入日期后会发生变化?

  14. 14

    为什么宽度属性在更改 html 中的填充属性时会发生变化

  15. 15

    为什么在 tensorflow 会话中访问 keras 模型参数值会发生变化?

  16. 16

    为什么在 Google Play API 中取消订阅后到期会发生变化?

  17. 17

    为什么在调用pop()之后top()的返回值会发生变化?

  18. 18

    为什么在 JSON.parse 调用后整数值会发生变化

  19. 19

    在什么情况下,azure 函数的授权密钥会发生变化?

  20. 20

    为什么在Webkit过滤器悬停时堆叠顺序会发生变化?

  21. 21

    为什么追加熊猫数据框时列顺序会发生变化?

  22. 22

    为什么玩家落在平台上时平台的速度会发生变化?

  23. 23

    为什么我移动时游戏中的事物会发生变化?Java处理环境

  24. 24

    为什么从左向右滚动时ui-grid的高度会发生变化?

  25. 25

    Python:为什么在使用 for 循环 for with float() 时每个元素的位置会发生变化

  26. 26

    为什么更改新列表时原始列表会发生变化?

  27. 27

    为什么包含选项卡时 printf 数字的结果会发生变化?

  28. 28

    为什么克隆时原始 django 对象会发生变化?

  29. 29

    Flask:为什么定义变量时 ajax 数据的内容会发生变化?

热门标签

归档