krl*_*mlr 11 shell bash pipe fifo
假设我有以下管道:
a | b | c | d
Run Code Online (Sandbox Code Playgroud)
我怎样才能在or 中等待c
(或b
)完成?这意味着该脚本可以开始任何时间(和它不是必须等待),但需要完整的输出正确地工作。sh
bash
d
c
用例是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
我找到了一个解决方案,欢迎评论(或更好的解决方案)。
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)
如果我正确理解你的问题,这应该有效:
a | b | c | { (exec <&3 3<&-; d) &} 3<&0
Run Code Online (Sandbox Code Playgroud)
(fd 3 技巧是因为某些(大多数)shell 将 stdin 重定向到 /dev/null with &
)。