script.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 -e
和set -o pipefail
的组合应该意味着false
传播到主脚本并终止于foo=...
但是foo被指定为“管道仍在运行”。 ..当我希望它不会时脚本继续。我原以为this question支持这个想法。
在阅读关于pipefail(特别是)的bash手册页后,它指出A pipeline is a sequence of one or more commands separated by one of the control operators ‘|’ or ‘|&’.
然后,我认为set
不会传播到子壳中?有没有办法让这种情况发生?
供参考,我正在使用
$ 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.
答案 0 :(得分:2)
与pipefail没什么关系。
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
已经发生过或没有发生过。{/ p>