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
How to Limit File Size on Commit
Linux Keyboard Event Capturing /Dev/Inputx
How to Execute Parallel "For" Loops in Bash
How to Display Only Files from Aws S3 Ls Command
Linux: How to Detect That Ftp File Upload Is Finished
Ps: Clean Way to Only Get Parent Processes
What Does -Prune Option in Find Do
Multiple Option Arguments Using Getopts (Bash)
How to Respond to Prompts in a Linux Bash Script Automatically
How to Rename Files You Put into a Tar Archive Using Linux 'Tar'
Increase of Virtual Memory Without Increse of Vmsize
X86 Linux Assembler Get Program Parameters from _Start
Get Parent Directory of a File in Bash
Setup Cron Tab to Specific Time of During Weekdays
How to Develop Opengl Es (Gles) 2.0 Applications on Linux
Evaluating Smi (System Management Interrupt) Latency on Linux-Centos/Intel MAChine
How to Translate Linux Keycodes from /Dev/Input/Event* to Ascii in Perl
Use Sed to Delete All Leading/Following Blank Spaces in a Text File