0

Let's say I'm running multiple instances of process w1 (from source code while1.c) in the background (while1.c contains an infinite while loop):

gcc while1.c -o w1
./w1&
./w1&
./w1&
./w1&

Now I want to get the PID of every instance. For that, I am doing this:

var=$(/bin/ps r -o pid,cmd|grep "w1"| grep -v "grep"|awk '{print $1}')

That will store the PIDs of all instances of w1 in $var.
So, if I do:

echo $var

It will print out the PIDs of all instances of w1.

But I want to access individual PIDs, i.e. something like:

echo ${var[0]}
echo ${var[1]}

And so on (something like arrays). How can I do that?

PS: echo ${var[0]} is printing all PIDs while echo ${var[1]} or echo ${var[2]} and so on, is printing nothing (i.e. blank lines of output).

2

Save the PIDs as you start the processes:

pids=()

./w1 & pids+=( "$!" )
./w1 & pids+=( "$!" )
./w1 & pids+=( "$!" )
./w1 & pids+=( "$!" )

(that's assuming a shell with bash-compatible array syntax)

Now you have the PIDs in the array pids and can access them as "${pids[0]}", "${pids[1]}", etc.

If you are using plain /bin/sh:

set --

./w1 & set -- "$@" "$!"
./w1 & set -- "$@" "$!"
./w1 & set -- "$@" "$!"
./w1 & set -- "$@" "$!"

Now you have the PIDs in the list "$@" and can access them as "$1", "$2", etc.

The special value "$!" will be the PID of the most recently started background command.

  • thanks that worked... – Arpit Goyal Sep 15 at 10:48
0

If you're running bash, you can use jobs -l, which lists background jobs along with their PIDs. For example, the following will store all the PIDs of jobs matching ./w1 into array pids:

pids=( $(jobs -l | awk '/\.\/w1/ {print $2}') )

In other shells, you could use ps --ppid $$ to list all the jobs with the current shell as parent:

pids=( $(ps --ppid $$ -o pid,cmd -h | awk '/\.\/w1/ {print $1}') )

NOTE: AFAIK, this is not portable - it will only work with ps from the Linux procps package. Other versions of ps don't have the same options.

With FreeBSD's ps, you could do something like this (in bash or ksh or some other shell that supports arrays):

pids=( $(ps -j | awk -v ppid=$$ '$3==ppid && /\.\/w1/ {print $2}') )

If you have pgrep available, you could use:

pids=( $(pgrep -P $$ w1) )

In all variants, I'm checking that the background process matches ./w1 - if you're certain that there's never going to be any other child or background processes of that PPID running, you can skip that test in the awk scripts (and only need to output -o pid in the second variant's ps command).

  • ps will work..../w1& ./w1& ./w1& ./w1& var=( $(/bin/ps r -o pid,cmd|grep "w1"| grep -v "grep"|awk '{print $1}') )...I was missing one set of parenthesis.... – Arpit Goyal Sep 15 at 10:42
  • BTW, you never need to pipe grep into awk. And you never need to do that annoying ps | grep | grep -v grep | awk thing. that's been around forever and it was never needed. awk alone is enough. – cas Sep 15 at 10:48
  • thanks @cas, I tried first two methods and both worked perfectly. And that pipe thing was indeed annoying, thanks for pointing that out and suggesting a better way. – Arpit Goyal Sep 15 at 12:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.