半异步管道

krl*_*mlr 11 shell bash pipe fifo

假设我有以下管道:

a | b | c | d
Run Code Online (Sandbox Code Playgroud)

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

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

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

编辑

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

wait $(a | b | { c & [print PID of c] ; } | d)
Run Code Online (Sandbox Code Playgroud)

编辑^2

我找到了一个解决方案,欢迎评论(或更好的解决方案)。

Hau*_*ing 6

a | b | { c; [notify];} | d
Run Code Online (Sandbox Code Playgroud)

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

另一个想法:

您从管道执行下一个进程(您正在等待的能够启动的进程):

a | b | { c; exec >&-; nextprocess;} | d
Run Code Online (Sandbox Code Playgroud)

或者

a | b | { c; exec >&-; nextprocess &} | d
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 5

如果我正确理解你的问题,这应该有效:

a | b | c | { (exec <&3 3<&-; d) &} 3<&0
Run Code Online (Sandbox Code Playgroud)

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