使用bash进程替换,我想同时在文件上运行两个不同的命令.在这个例子中,没有必要,但想象"cat/usr/share/dict/words"是一个非常昂贵的操作,例如解压缩50gb文件.
cat /usr/share/dict/words | tee >(head -1 > h.txt) >(tail -1 > t.txt) > /dev/null
Run Code Online (Sandbox Code Playgroud)
在这个命令之后我希望h.txt包含单词文件"A"的第一行,并且t.txt包含文件"Zyzzogeton"的最后一行.
然而实际发生的是h.txt包含"A"但是t.txt包含"argillaceo",它大约是文件的5%.
为什么会这样?似乎要么"尾巴"进程提前终止,要么流正在混淆.
像这样运行另一个类似命令的行为符合预期:
cat /usr/share/dict/words | tee >(grep ^a > a.txt) >(grep ^z > z.txt) > /dev/null
Run Code Online (Sandbox Code Playgroud)
在这个命令之后,我希望a.txt包含所有以"a"开头的单词,而z.txt包含所有以"z"开头的单词,这正是发生的事情.
那么为什么这不适用于"尾巴",以及其他命令会不起作用?
如果在管道的任何步骤中存在非零错误的情况下捕获到非零错误,则设置bash pipefail选项(via set -o pipefail)允许脚本失败.
但是,我们SIGPIPE遇到了错误(错误代码141),其中数据被写入不再存在的管道.
有没有办法设置bash来忽略SIGPIPE错误,或者是否有一种方法来编写一个错误处理程序来处理所有错误状态代码,比如0和141?
例如,在Python中,我们可以添加:
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
Run Code Online (Sandbox Code Playgroud)
将默认行为应用于SIGPIPE错误:忽略它们(参见http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-06/3823.html).
bash中是否有类似的选项?
获取管道命令的退出代码工作正常。
echo "ABC" | false | true
echo ${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]}
#Output is 0 1 0
Run Code Online (Sandbox Code Playgroud)
但是当我将输出分配给一个变量时,无法获得退出代码。
TEST=$(echo "ABC" | false | true)
echo ${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]}
#Output is 0
Run Code Online (Sandbox Code Playgroud)
如何获取管道进程的退出代码?
我运行git log命令(通常有更多选项,这里无关紧要)然后退出q。但是,在我最近安装了 zsh 插件以显示最后一个命令返回码后,我发现此命令以非零返回码退出。
$ git log
$ echo $?
141
Run Code Online (Sandbox Code Playgroud)
为什么会发生这种情况,这是任何真正潜在问题的迹象,我该如何解决?
如果我有任意数量的管道源和接收器
exec1 | exec2 | exec3 | ...
题
execN退出,所有execM下游(M > N)也会退出吗?