半异步管


11

假设我有以下管道:

a | b | c | d

我如何可以等待完成c(或b)在shbash?这意味着该脚本d可以开始任何时间(和它不是必须等待),但需要完整的输出c正确地工作。

用例是difftool用于git比较图像的。它由调用,git并需要处理其输入(a | b | c部分)并显示比较结果(d部分)。呼叫者将删除a和所需的输入b。这意味着在从脚本返回之前,进程c(或b)必须终止。另一方面,我不能等待,d因为这意味着我正在等待用户输入。

我知道我可以将的结果写入c一个临时文件,或者在中使用FIFO bash。(不过,不确定FIFO是否会有所帮助。)在没有临时文件的情况下是否可以实现此目的sh

编辑

如果我能以可靠的方式找出c(或b)进程的进程ID,也许就足够了。然后整个管道可以异步启动,我可以等待进程ID。遵循以下原则

wait $(a | b | { c & [print PID of c] ; } | d)

编辑^ 2

我已经找到了解决方案,欢迎提出评论(或更好的解决方案)。


您是说要在完成后才d开始处理c输出c?您不想d开始处理每条输出线吗?
terdon

@terdon:不,d可以随意开始,但是c需要完成后才能继续。
krlmlr 2014年

这似乎是自相矛盾的,如果d可以在喜欢的时候开始,那您还等什么呢?
terdon

@terdon:扩展为显示用例。
krlmlr 2014年

如果d不使用的输出,c那么d组成管道的一部分似乎没有任何意义。但是,如果d确实使用了输入,那么d在阅读完所有输入后必须在其输入上工作一段时间,以使您的方法有所不同。
Hauke Laging

Answers:


6
a | b | { c; [notify];} | d

该通知可以例如通过已在环境变量(kill -USR1 $EXTPID)中传递给PID的信号或通过创建文件(touch /path/to/file)来完成。

另一个想法:

您从管道中执行下一个过程(等待您开始的过程):

a | b | { c; exec >&-; nextprocess;} | d

要么

a | b | { c; exec >&-; nextprocess &} | d

谢谢。但是,为中间输出创建一个临时文件更加冗长且易于解析(对于人类而言)。另外,如何避免信号出现竞争状况?...我一直希望有一个更清洁的解决方案,但是如果这是要走的路,那就这样吧。
krlmlr 2014年

@krlmlr什么种族条件?
Hauke Laging

notify可以在设置信号陷阱之前执行。如何确保不错过该信号?
krlmlr 2014年

@krlmlr您可以停止调用管道的脚本,直到脚本收到定义了信号之后发送的信号本身为止trap
Hauke Laging

您的编辑:管道在一个循环中被调用,对此我无法控制。不幸的是,{ c; bg; }或者{ c; exit 0; }似乎不起作用。
krlmlr 2014年

5

如果我正确理解了您的问题,则该方法应该起作用:

a | b | c | { (exec <&3 3<&-; d) &} 3<&0

(fd 3的技巧是因为某些(大多数)shell使用将stdin重定向到/ dev / null &)。



3

这是我在Hauke的帮助下通过反复试验发现的:

a | b | { c; kill -PIPE $$; } | d

等效地:

a | b | ( c; kill -PIPE $$; ) | d

(后者更为明确,因为{}无论如何,如果在管道内,它将在子外壳中运行。)

一些其他信号(包括QUITTERMUSR1)工作,也不过在这种情况下被示出在终端上的信号的描述。

我想知道这是否是PIPE信号的初衷。根据手册

SIGPIPE:当PIPE信号试图写入未连接另一端的进程的管道时,该信号被发送到进程。

这意味着当我人为地将管道信号发送到子shell时,它会静默终止,而不会留下最终使用者(d)。

这适用于shbash


0

您可以使用sponge“ moreutils”包中的程序:

a | b | c | sponge | d

用海绵将其c输送到管道的末端d。希望那是您想要的。


0

您可以这样做:

a | b | c | (d ; cat > /dev/null)

因此,d完成后,cat将会吸收的其余c输出,直到完成为止。

好。经过评论,我认为答案是直接d在后台开始。

做:

a | b | c | (d &)

如果在读取stdin时遇到问题,请使用Stephane Chazelas的解决方案。d


恐怕我的用例恰恰相反:c完成时间早于d,我必须等到c完成但不关心d
krlmlr 2014年

对不起,我不明白。c完成并d仍在运行时,您想做什么?杀了d
安格斯2014年

d具有GUI,并且可以运行直到用户关闭它。
krlmlr 2014年

好的...但这已经发生了。当abc完成工作时,他们关闭stdout并退出;并且仅d保持运行状态。您要dc完成后发送到后台吗?是吗
2014年

是的,完成后d应发送到后台c
krlmlr 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.