l0b*_*0b0 18 bash process-substitution
(可能与某些程序有关,不接受输入文件的进程替换?)
在一些Bash单元测试脚本中,我使用以下技巧来记录和显示命令的stdout和stderr:
command > >(tee "${stdoutF}") 2> >(tee "${stderrF}" >&2)
Run Code Online (Sandbox Code Playgroud)
此过程会向stdout生成一些输出,因此$stdoutF文件会获取一些数据.然后我运行另一个不输出任何数据的命令:
diff -r "$source" "$target" > >(tee "${stdoutF}") 2> >(tee "${stderrF}" >&2)
Run Code Online (Sandbox Code Playgroud)
但是,在运行空白测试(使用shunit-ng)之前,此过程看起来并不总是成功完成:
assertNull 'Unexpected output to stdout' "$(<"$stdoutF")"
Run Code Online (Sandbox Code Playgroud)
在100次运行测试中,这次失败了25次.
sync在测试文件空虚之前调用它是否足够:
sync
assertNull 'Unexpected output to stdout' "$(<"$stdoutF")"
Run Code Online (Sandbox Code Playgroud)
...和/或它应该通过强制执行命令的顺序来工作:
diff -r "$source" "$target" \
> >(tee "${stdoutF}"; assertNull 'Unexpected output to stdout' "$(<"$stdoutF")")
2> >(tee "${stderrF}" >&2)
Run Code Online (Sandbox Code Playgroud)
...和/或它可能以tee某种方式assertNull直接而不是文件?
更新:sync不是答案 - 请参阅下面的Gilles回复.
更新2:进一步讨论同步保存stdout,stderr和stdout + stderr.谢谢你的回答!
Gil*_*il' 27
在bash中,进程替换替换命令在foo > >(bar)完成后立即foo结束.(文档中未对此进行讨论.)您可以查看此内容
: > >(sleep 1; echo a)
Run Code Online (Sandbox Code Playgroud)
此命令立即返回,然后在a一秒后异步打印.
在您的情况下,该tee命令只需要一点点时间就可以在完成后command完成.添加sync给了tee足够的时间来完成,但这并没有消除竞争条件,只是添加一个sleep遗嘱,它只是使竞争更不可能显现.
更一般地说,sync没有任何内部可观察到的影响:如果您想访问文件系统存储在不同操作系统实例下的设备,它只会产生影响.更清楚地说,如果您的系统断电,只有sync在重新启动后才能保证在最后一次之前写入的数据可用.
至于消除竞争条件,这里有一些可能的方法:
明确同步所有替换过程.
mkfifo sync.pipe
command > >(tee -- "$stdoutF"; echo >sync.pipe)
2> >(tee -- "$stderrF"; echo >sync.pipe)
read line < sync.pipe; read line < sync.pipe
Run Code Online (Sandbox Code Playgroud)每一个命令,而不是重用使用不同的临时文件名$stdoutF和$stderrF,并执行该临时文件始终是新创建的.
放弃进程替换并改用管道.
{ { command | tee -- "$stdoutF" 1>&3; } 2>&1 \
| tee -- "$stderrF" 1>&2; } 3>&1
Run Code Online (Sandbox Code Playgroud)
如果你需要命令的返回状态,bash会把它放入${PIPESTATUS[0]}.
{ { command | tee -- "$stdoutF" 1>&3; exit ${PIPESTATUS[0]}; } 2>&1 \
| tee -- "$stderrF" 1>&2; } 3>&1
if [ ${PIPESTATUS[0]} -ne 0 ]; then echo command failed; fi
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
3867 次 |
| 最近记录: |