请考虑以下简化示例:
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.
注意:更改cat为awk '...'帮助澄清我需要的内容.
小智 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.
我可以使用显式命名管道来解决此问题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的管理。希望有人有一个更简单的解决方案。
这是一个没有包装器或临时文件的解决方案.这仅适用于背景管道,其输出从包含脚本的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