bash 脚本从函数返回后意外退出

M. *_*ter 3 linux bash shell stdout execution

这是我关于堆栈溢出的上一个问题的后续问题。我会将脚本缩减为基本部分,但如果这样认为,了解脚本的作用可能会有所帮助,您可以研究其他问题。

 #!/usr/bin/env bash
 set -eu -o pipefail

 declare -a framelist


 #Print all results

 function output_values() {
   echo "Results!";
 }

 #parsing information from stdin

 function parser () {

   while read tc;
     do

      if [ -z "$tc" ]; then
        continue
      fi

      #Evaluation and saving result to array

      echo $result_value;

      framelist+=($result_value);

      if (( <<some abort condition>> )); then
        exec 0>&-
        echo "Last result: $result_value";
        return 0
      fi

     done
 }

 some_command_writing_to_stdout | parser $2;
 output_values;
Run Code Online (Sandbox Code Playgroud)

该脚本执行命令并将输出通过管道传输到我的本地函数,该函数最终按echo "Last result: $result_value";预期返回该行的结果。此后,它将终止提供在此函数中解析的数据的命令 - 这也有效。

当到达 时return 0,我认为output_values;应该执行脚本的下一行(命令的正下方),但事实并非如此。

即使我直接在 echo 行之前调用 output_values 函数(在解析器函数中打印结果),它也不会被执行。

它变得更加奇怪,因为我可以注释掉exec 0>&-并且所有行为都一样。一旦退出解析器函数,即使应该由该行终止的命令也会被终止。

我必须更改什么才能在解析器函数返回后处理它的结果?这不可能是有意的行为。

问候

曼努埃尔

ran*_*mir 5

让我们看一下man bash,部分pipefail

pipefail

如果设置,管道的返回值是最后一个(最右边)以非零状态退出的命令的值,如果管道中的所有命令都成功退出,则返回值为零。默认情况下禁用此选项。

与 结合set -e,每当命令(管道)以非零退出状态退出时,它将退出,唯一的逻辑结论是: some_command_writing_to_stdout必须以非零退出状态退出(因为显然,parser存在于0)。

这可以解释为什么管道 ( parser) 中的下一个命令被执行,以及为什么脚本在此之后完成。

验证这一点很容易。只需将倒数第二条语句替换为:

(some_command_writing_to_stdout || true) | parser $2
Run Code Online (Sandbox Code Playgroud)