如何在管道中获取进程的PID

Use*_*er1 14 bash awk

请考虑以下简化示例:


my_prog|awk '...' > output.csv &
my_pid="$!" #Gives the PID for awk instead of for my_prog
sleep 10
kill $my_pid #my_prog still has data in its buffer that awk never saw. Data is lost!

在bash中,$my_pid指向PID awk.但是,我需要PID my_prog.如果我杀了awk,my_prog不知道要刷新它的输出缓冲区并且数据丢失了.那么,如何获得PID my_prog呢?请注意,ps aux|grep my_prog由于可能会有几个工作,因此无法使用my_prog.

注意:更改catawk '...'帮助澄清我需要的内容.

小智 8

刚刚遇到同样的问题.我的解决方案

process_1 | process_2 &
PID_OF_PROCESS_2=$!
PID_OF_PROCESS_1=`jobs -p`
Run Code Online (Sandbox Code Playgroud)

只需确保process_1是第一个后台进程.否则,您需要解析完整的输出jobs -l.


Use*_*er1 6

我可以使用显式命名管道来解决此问题mkfifo

步骤1 : mkfifo capture

步骤2:执行这个指令码


my_prog > capture &
my_pid="$!" #Now, I have the PID for my_prog!
awk '...' capture > out.csv & 
sleep 10
kill $my_pid #kill my_prog
wait #wait for awk to finish.

我不喜欢拥有mkfifo的管理。希望有人有一个更简单的解决方案。


Mat*_*vid 5

这是一个没有包装器或临时文件的解决方案.这仅适用于背景管道,其输出从包含脚本的stdout捕获,如您的情况.假设你想做:

cmd1 | cmd2 | cmd3 >pipe_out &
# do something with PID of cmd2
Run Code Online (Sandbox Code Playgroud)

如果只有bash可以提供${PIPEPID[n]}!我找到的替代"黑客"如下:

PID=$( { cmd1 | { cmd2 0<&4 & echo $! >&3 ; } 4<&0 | cmd3 >pipe_out & } 3>&1 | head -1 )
Run Code Online (Sandbox Code Playgroud)

如果需要,您还可以分别用和关闭fd 3(for cmd*)和fd 4(for cmd2).如果你这样做,为了确保你只有从它重定向fd 0 关闭fd 4 .3>&-4<&-cmd2