How to Get Pid from Forked Child Process in Shell Script

How to get PID from forked child process in shell script

The PID of a backgrounded child process is stored in $!, and the current process is $$:

fpfunction &
child_pid=$! # in parent process, child's pid is $!
parent_pid=$$ # in parent process, parent's pid is $$

When in the backgrounded function, the child processes's PID is $BASHPID rather than $$, which is now the parent's PID:

fpfunction() {
local child_pid=$BASHPID # in child process, child's pid is $BASHPID
local parent_pid=$$ # in child process, parent's pid is $$
...
}

Also for what it's worth, you can combine the looping statements into a single C-like for loop:

for ((n = 1; n < 20; ++n)); do
echo "Hello World-- $n times"
sleep 2
echo "Hello World2-- $n times"
done

PID of all child processes of a command

Update: In the comments below my answer it turned out that:

I need something that observes the creation of all child processes during a span of time. Given that, filtering to isolate my subtree will not be difficult.

... was the intention behind the question and it was for debugging purposes.

In that case I'd recommend to use strace like this:

strace -f command

-f will track child processes - recursively. Since forking and exec-ing requires system calls, strace will list any child creation plus the pids.


Original answer:

You can use pgrep for that:

run_process &
pid=${!}
pgrep --parent "${pid}"
wait # wait for run_process to finish

Btw, you may want to use the pstree command, it is nice to use:

run_process &
pid=${!}
pstree -p "${pid}"
wait # wait for run_process to finish

Anyhow, you'll need to install pstree.

How to get child process from parent process

Just use :

pgrep -P $your_process1_pid

How to get child PID in C?

fork already returns the child's pid. Just store the return value.

look at man 2 fork:

RETURN VALUES

 Upon successful completion, fork() returns a value of 0 to the child process and
returns the process ID of the child process to the parent process. Otherwise, a
value of -1 is returned to the parent process, no child process is created, and
the global variable errno is set to indicate the error.

How does fork return a Pid?

under the hood fork looks something as following:

int fork() {
1. generate a new PID for child // executed only by parent process
2. do million more things required to create a process // executed only by parent
/* now we have a new process in the system, which can be scheduled on CPU */
3. finally return value of a specific CPU register // executed by both parent and child
// Note that at this point we have two processes,
// in case of child process the CPU register contains 0 (fork returns 0 to child)
// in case of parent process register contains PID of child
}

So as you can see fork in parent process doesn't have to wait for child in order to return the child's PID, as it was already available to parent process.

Fork command in shell to print process ids

The parent is exiting before the child performs its printf call. When the parent exits, the child gets a new parent. By default this is the init process, PID 1. But recent versions of Unix have added the ability for a process to declare itself to be the "subreaper", which inherits all orphaned children. PID 1910 is apparently the subreaper on your system. See https://unix.stackexchange.com/a/177361/61098 for more information about this.

Put a wait() call in the parent process to make it wait for the child to exit before it continues.

#include <stdio.h>
#include <unistd.h>

int main(void)
{
int pid;
pid=fork();
if(pid==0) {
printf("I am the child.My pid is %d .My parents pid is %d \n",getpid(),getppid());
} else {
printf("I am the parent.My pid is %d. My childs pid is %d \n",getpid(),pid);
wait(NULL);
}
return 0;
}

bash getting background process id gives parent pid

You already get the right information about the child process. Only in your case, ps doesn't know or want to show a proper COMMAND name for your chained sub-process you start in the background - what probably confused you.

Looks like this is the case with the chained commands (.. && ..., thus it has nothing to do with exit 1 could be also echo 5 etc.) where the process group leader name is showed as cmd name instead.

From the (ps man page)

`cmd | COMMAND`: simple name of executable

# Process state codes
`S`: interruptible sleep (waiting for an event to complete)
`+`: is in the foreground process group

See the S+ in your ps | grep output.

So, you can adapt your script a bit to confirm that you actually capture(d) the right information about the child process, like so:

cat <<"END"> z
#! /bin/bash

sleep 20 && exit 1 &
ret=$!

echo $ret

jobs -l

# display parent and child process info
# -j Jobs format
ps -j $$ $ret
END

Output of echo $ret:

30274

Output of jobs -l:

[1]+ 30274 Running                 sleep 20 && exit 1 &

Output of ps -j $$ $ret:

PID   PGID   SID   TTY    STAT    TIME COMMAND
30273 30273 21804 pts/0 S+ 0:00 /bin/bash ./z
30274 30273 21804 pts/0 S+ 0:00 /bin/bash ./z

Note that both the parent and child have the same PGID, whereas the pid 30274 of the child process displayed by jobs -l and ps ... matches.

Further, if you change sleep 20 && exit 1 & as bash -c 'sleep 20 && exit 1' & you would get a proper command name for the child this time, as follows (cf. output order above):

30384

[1]+ 30384 Running bash -c 'sleep 20 && exit 1' &

PID PGID SID TTY STAT TIME COMMAND
30383 30383 21804 pts/0 S+ 0:00 /bin/bash ./z
30384 30383 21804 pts/0 S+ 0:00 bash -c sleep 20 && exit 1

Last but not least, in your original version instead of ps $ret | grep $ret you could also try

pstree -s $ret

From pstree man page

-s: Show parent processes of the specified process.

Which will provide you with an output similar to that one below, which would also confirm that you get the right process info for sleep 20 && exit 1 &:

systemd───systemd───gnome-terminal-───bash───bash───sleep

How to get all descendent child process id of pid in c in linux

Iterating through /proc is the "standard" way to do this. That's how ps and friends (pstree, etc.) are implemented.



Related Topics



Leave a reply



Submit