bash进程替换和同步 [英] Bash process substitution and syncing

查看:149
本文介绍了bash进程替换和同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(可能与<一个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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆