微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Bash进程替换和同步

(可能与 Do some programs not accept process substitution for input files?有关)

在一些Bash单元测试脚本中,我使用以下技巧来记录和显示命令的stdout和stderr:

command > >(tee "${stdoutF}") 2> >(tee "${stderrF}" >&2)

这个过程产生一些stdout的输出,所以$stdoutF文件获取一些数据.然后我运行另一个输出任何数据的命令:

diff -r "$source" "$target" > >(tee "${stdoutF}") 2> >(tee "${stderrF}" >&2)

但是,在空虚测试运行之前,这个过程看起来并不总是成功完成(使用shunit-ng):

assertNull 'Unexpected output to stdout' "$(<"$stdoutF")"

在100次运行测试中,这次失败了25次.

在空档测试文件之前,应该调用sync吗?

sync
assertNull 'Unexpected output to stdout' "$(<"$stdoutF")"

…和/或应该通过强制命令的顺序工作:

diff -r "$source" "$target" \
> >(tee "${stdoutF}"; assertNull 'Unexpected output to stdout' "$(<"$stdoutF")")
2> >(tee "${stderrF}" >&2)

…和/或是否可以以某种方式开始直接取代文件

更新:同步不是答案 – 参见下面的吉尔斯回应.

更新2:进一步讨论Save stdout,stderr and stdout+stderr synchronously.感谢您的答案!

在bash中,进程替换替换命令foo>一旦完成,(bar)即可完成. (这在文档中没有讨论.)您可以检查
: > >(sleep 1; echo a)

此命令立即返回,然后一秒钟以异步方式打印.

在你的情况下,命令完成后,tee命令只需要一点时间才能完成.添加同步功能给了足够的时间来完成,但是这并不能消除比赛条件,只要添加一个睡眠就可以让比赛更不可能出现.

更一般地说,sync不具有任何内部可观察的效果:如果您想访问您的文件系统存储在不同操作系统实例下的设备,它只会有所不同.更清楚地说,如果您的系统失去电力,则只有在重新启动之前,才能保证在上次同步前写入的数据可用.

至于取消比赛条件,以下是一些可能的方法

>明确地同步所有替代的进程.

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,并强制临时文件总是新创建的.
放弃流程替换,改用管道.

{ { command | tee -- "$stdoutF" 1>&3; } 2>&1 \
            | tee -- "$stderrF" 1>&2; } 3>&1

如果您需要命令的返回状态,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

原文地址:https://www.jb51.cc/bash/386628.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐