命名管道不会等到在 bash 中完成
Posted
技术标签:
【中文标题】命名管道不会等到在 bash 中完成【英文标题】:Named pipe does not wait until completion in bash 【发布时间】:2018-01-29 22:09:12 【问题描述】:在下面的 test.jl 中创建一个 output.txt 并生成一些控制台输出。控制台输出处理得很好。但是在完全创建 output.txt 之前,控制权会在 echo 之后立即返回。在 echo 和 mv 之间放置一个等待会导致无限期的等待。是否应该在不终止管道的情况下将回车传递给管道?
mkfifo pipe
sleep 1000000 > pipe &
julia <pipe >stdout.txt 2>stderr.txt &
echo "include(\"test.jl\")" > pipe
mv output.txt temp/
echo "include(\"test2.jl\")" > pipe
谢谢!
【问题讨论】:
您要求julia
在后台创建文件,然后立即尝试移动它。这是一个竞争条件。你需要找到一种方法来等待它。方法包括为每个实例运行一个julia
实例,以便您可以等待进程退出,让程序将一些内容记录到您可以定期检查的 stdout.txt 中,猜测它需要不到 60 秒并休眠这么长,或者在完成后让test.jl
自己移动文件。
想一想如果行为与此不同会产生什么影响,并且程序必须等待其写入的内容在下游完全处理,然后才能从写入操作中重新获得控制权——如果你是运行find
管道进入xargs rm
,它无法继续找到第二个文件,直到第一个文件被完全删除。当此类处理完成时,您需要提出一套全新的流量控制结构来进行通信——您将获得什么价值?
【参考方案1】:
我知道test.jl
和test2.jl
都写入output.txt
,因此您必须在运行test2.jl
或test2.jl
之前将文件移动到另一个目录@ 预计output.txt
在temp/
目录中,你有在text2.jl
运行之前将其移动到那里。
如果是,那么下面的代码应该可以解决问题:
mkfifo pipe
sleep 1000000 > pipe &
julia <pipe >stdout.txt 2>stderr.txt &
echo "include(\"test.jl\")" > pipe
echo "mv(\"output.txt\", \"temp/\")" > pipe
echo "include(\"test2.jl\")" > pipe
Julia 以这种方式运行mv
命令,并确保它在test.jl
之后但在test2.jl
之前执行。
但实际上我们已经到了编写一个名为 e.g. 的 Julia 脚本会更好的地步。 script.jl
:
include("test.jl")
mv("output.txt", "temp/")
include("test2.jl")
并使用julia script.jl
运行它。
【讨论】:
保留 OP 的sleep
hack 是不幸的。考虑将其替换为 (after julia
调用) exec 3>pipe
,然后在输出端使用 >&3
执行 echo
s;这样,只有一个用于管道输入端的文件描述符保持打开状态,而不是让其上的 FD 数量随时间变化。
有没有更好的方法让命名管道保持打开状态,这样 Julia 在第一个 echo
之后就不会收到 EOF?我们假设一个交互式会话 - 而不是脚本 - Julia 在后台运行。
我在上述评论中建议的方法就是这样做的。 exec 3>pipe
在交互式会话中完全有效。
谢谢。我在并行写作。
(当你确实想关闭管道时,顺便说一下,你可以用exec 3>&-
来做到这一点。以上是关于命名管道不会等到在 bash 中完成的主要内容,如果未能解决你的问题,请参考以下文章
可能的竞争条件,来自多个 tee 接收者的管道输出在 BASH 脚本中的命名管道上无序到达