How to get the PID of a process in a pipeline

前端 未结 9 595
北海茫月
北海茫月 2020-12-03 01:51

Consider the following simplified example:


my_prog|awk \'...\' > output.csv &
my_pid=\"$!\" #Gives the PID for awk instead of for my_prog
sleep 10
kill $my         


        
9条回答
  •  鱼传尺愫
    2020-12-03 02:43

    My solution was to query jobs and parse it using perl.
    Start two pipelines in the background:

    $ sleep 600 | sleep 600 |sleep 600 |sleep 600 |sleep 600 &
    $ sleep 600 | sleep 600 |sleep 600 |sleep 600 |sleep 600 &
    

    Query background jobs:

    $ jobs
    [1]-  Running                 sleep 600 | sleep 600 | sleep 600 | sleep 600 | sleep 600 &
    [2]+  Running                 sleep 600 | sleep 600 | sleep 600 | sleep 600 | sleep 600 &
    
    $ jobs -l
    [1]-  6108 Running                 sleep 600
          6109                       | sleep 600
          6110                       | sleep 600
          6111                       | sleep 600
          6112                       | sleep 600 &
    [2]+  6114 Running                 sleep 600
          6115                       | sleep 600
          6116                       | sleep 600
          6117                       | sleep 600
          6118                       | sleep 600 &
    

    Parse the jobs list of the second job %2. The parsing is probably error prone, but in these cases it works. We aim to capture the first number followed by a space. It is stored into the variable pids as an array using the parenthesis:

    $ pids=($(jobs -l %2 | perl -pe '/(\d+) /; $_=$1 . "\n"'))
    $ echo $pids
    6114
    $ echo ${pids[*]}
    6114 6115 6116 6117 6118
    $ echo ${pids[2]}
    6116
    $ echo ${pids[4]}
    6118
    

    And for the first pipeline:

    $ pids=($(jobs -l %1 | perl -pe '/(\d+) /; $_=$1 . "\n"'))
    $ echo ${pids[2]}
    6110
    $ echo ${pids[4]}
    6112
    

    We could wrap this into a little alias/function:

    function pipeid() { jobs -l ${1:-%%} | perl -pe '/(\d+) /; $_=$1 . "\n"'; }
    $ pids=($(pipeid))     # PIDs of last job
    $ pids=($(pipeid %1))  # PIDs of first job
    

    I have tested this in bash and zsh. Unfortunately, in bash I could not pipe the output of pipeid into another command. Probably because that pipeline is ran in a sub shell not able to query the job list??

提交回复
热议问题