gpt4 book ai didi

linux - 在进程替换中的命令失败后,bash pipefail 仍在运行 w/set -e

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

脚本.sh:

set -x
set -e
set -u
set -o pipefail

foo=$(tail -1 <(false || { >&2 echo "failed" && exit 1; }) | echo "pipeline still running" || { >&2 echo "failed" && exit 1; }) || { >&2 echo "failed" && exit 1; }

echo "Script still running..."

为什么 echo "Script still running..." 最终被执行了?我认为 set -eset -o pipefail 的组合应该意味着 false 传播到主脚本并终止于 foo=... 但 foo 被分配为“管道仍在运行”...并且脚本在我希望它不会继续运行时继续。我以为this question支持这个想法。

在阅读关于 pipefail 的 bash 手册页(特别是)后,它声明 管道是由控制运算符“|”或“|&”之一分隔的一个或多个命令的序列。

那么,我认为 set 不会传播到子 shell 中?有没有办法让这种情况发生?

作为引用,我正在使用

$ bash --version
GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

最佳答案

与管道失败无关。

cat <(exit 1)

...退出状态为 0,设置或不设置 pipefail:进程替换不是管道组件,不会检查它们的退出状态。

也就是说,在 bash 4.4 及更高版本中,您可以按如下方式明确检查它:

cat <(exit 1); pid=$!
wait "$pid" # this will have the exit status of the process substitution operation

顺便说一句,这有令人信服的理由。考虑:

exec 3< <(echo hello; exit 1)
read greeting <&3
echo "Greeting is: $greeting"

现在,您希望哪个命令失败?它不可能是实际执行进程替换重定向的那个,因为进程替换在该单个命令执行之后仍然处于事件状态,并且在发生 read 之前,进程替换 还没有失败

它不会可靠地是read greeting,因为读取成功——只有与该读取关联的写入完成后管道另一端的进程失败,并且不能保证 exit 在外壳进入最终 echo 之前发生或没有发生。

关于linux - 在进程替换中的命令失败后,bash pipefail 仍在运行 w/set -e,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42703281/

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