bash进程替换和同步 [英] Bash process substitution and syncing
问题描述
(可能与<一个href=\"http://stackoverflow.com/questions/4274171/do-some-programs-not-accept-process-substitution-for-input-files\">Do某些程序不接受输入的文件,进程替换?)
在某些猛砸单元测试脚本我使用下面的技巧来登录的和的显示输出和命令的标准错误:
In some Bash unit test scripts I'm using the following trick to log and display stdout and stderr of a command:
command > >(tee "${stdoutF}") 2> >(tee "${stderrF}" >&2)
这过程中产生的一些输出到标准输出,因此 $ stdoutF
文件中获取的一些数据。然后我运行另一个命令,它不输出任何数据:
This process produces some output to stdout, so the $stdoutF
file gets some data. Then I run another command which does not output any data:
diff -r "$source" "$target" > >(tee "${stdoutF}") 2> >(tee "${stderrF}" >&2)
但是,它看起来并不像这个过程中始终成功完成测试的空虚运行之前(使用 shunit-NG 一>)
assertNull 'Unexpected output to stdout' "$(<"$stdoutF")"
在100运行测试这个失败的25倍。
In a 100 run test this failed 25 times.
如果它足以叫同步
测试文件空虚前:
Should it be sufficient to call sync
before testing the file for emptiness:
sync
assertNull 'Unexpected output to stdout' "$(<"$stdoutF")"
...和/或它应该通过迫使命令序列工作:
... and/or should it work by forcing the sequence of the commands:
diff -r "$source" "$target" \
> >(tee "${stdoutF}"; assertNull 'Unexpected output to stdout' "$(<"$stdoutF")")
2> >(tee "${stderrF}" >&2)
...和/或是否有可能 T恤
什么办法 assertNull
,而不是直接的文件?
... and/or is it possible to tee
it somehow to assertNull
directly instead of a file?
更新:同步
不是答案 - 请参见下面吉尔的回应
Update: sync
is not the answer - See Gilles' response below.
更新2 :讨论进一步采取<一个href=\"http://stackoverflow.com/questions/4497817/save-stdout-stderr-and-stdoutstderr-synchronously\">Save标准输出,标准错误和标准输出+标准错误同步的。感谢您的答案!
Update 2: Discussion taken further to Save stdout, stderr and stdout+stderr synchronously. Thanks for the answers!
推荐答案
在bash中,一个过程换人命令富&GT; &GT;(巴)
尽快富
结束结束。 (这不是在文档中进行讨论。)您可以检查此以
In bash, a process substitution substitution command foo > >(bar)
finishes as soon as foo
finishes. (This is not discussed in the documentation.) You can check this with
: > >(sleep 1; echo a)
此命令立即返回,然后打印 A
异步一秒钟后。
This command returns immediately, then prints a
asynchronously one second later.
在你的情况下, T恤
命令将只是一个时间的点点命令后,完成
完成。添加同步
给 T恤
足够的时间来完成,但是这不会删除竞态条件,不是添加更多睡眠
会,它只是使比赛更不可能体现。
In your case, the tee
command takes just one little bit of time to finish after command
completes. Adding sync
gave tee
enough time to complete, but this doesn't remove the race condition, any more than adding a sleep
would, it just makes the race more unlikely to manifest.
更一般地,同步
并没有任何内部的显着影响:它只是有差别,如果你要访问您的文件系统存储在不同的操作系统实例下设备。在清晰的条款,如果你的系统断电,最后同步之前只写数据
保证是你重新启动后可用。
More generally, sync
does not have any internally observable effect: it only makes a difference if you want to access device where your filesystems are stored under a different operating system instance. In clearer terms, if your system loses power, only data written before the last sync
is guaranteed to be available after you reboot.
作为除去竞争条件,这里有一些可能的方法:
As for removing the race condition, here are a few of possible approaches:
-
显式同步所有取代的过程。
Explicitly synchronize all substituted processes.
mkfifo sync.pipe
command > >(tee -- "$stdoutF"; echo >sync.pipe)
2> >(tee -- "$stderrF"; echo >sync.pipe)
read line < sync.pipe; read line < sync.pipe
每一个命令,而不是重用使用不同的临时文件名 $ stdoutF
和 $ stderrF
,和执行临时文件总是新创建的。
Use a different temporary file name for each command instead of reusing $stdoutF
and $stderrF
, and enforce that the temporary file is always newly created.
放弃进程替换和使用管道来代替。
Give up on process substitution and use pipes instead.
{ { command | tee -- "$stdoutF" 1>&3; } 2>&1 \
| tee -- "$stderrF" 1>&2; } 3>&1
如果您需要的命令的返回状态,庆典将其放在 $ {PIPESTATUS [0]}
。
If you need the command's return status, bash puts it in ${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
这篇关于bash进程替换和同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!