in reply to Re^4: Obtain the child process id in perl
in thread Obtain the child process id in perl

In general, you can't, unless you somehow have the actual application communicate its PID.  Problem is that the child process may fork any number of subprocesses, so the immediate child is not necessarily the application you're interested in.

But if the idea is to kill a hanging application, you could maybe create a new process group, and then kill that entire process group.

Update:

#!/usr/bin/perl if (my $pid = fork()) { # kill process group after timeout sleep 3; show_procs(); kill -9, $pid; # negative signal number kills group wait; print "killed children\n"; show_procs(); # show remaining processes # ... } elsif (defined $pid) { setpgrp; # create new process group # run something (consisting of several processes) that takes a whi +le exec 'find / | grep foo'; } else { die "couldn't fork"; } sub show_procs { system "ps Tf -o pid,ppid,pgrp,sid,cmd"; } __END__ $ ./841709.pl PID PPID PGRP SID CMD 12046 12044 12046 12046 bash -rcfile .bashrc 3881 12046 3881 12046 \_ /usr/bin/perl ./841709.pl 3882 3881 3882 12046 \_ sh -c find / | grep foo 3883 3882 3882 12046 | \_ find / 3884 3882 3882 12046 | \_ grep foo 3885 3881 3881 12046 \_ ps Tf -o pid,ppid,pgrp,sid,cmd killed children PID PPID PGRP SID CMD 12046 12044 12046 12046 bash -rcfile .bashrc 3881 12046 3881 12046 \_ /usr/bin/perl ./841709.pl 3886 3881 3881 12046 \_ ps Tf -o pid,ppid,pgrp,sid,cmd

(3882 is the PGRP in question here)

Replies are listed 'Best First'.
Re^6: Obtain the child process id in perl
by Anonymous Monk on May 26, 2010 at 12:53 UTC

    Consider the following example. There I used setpgrp to make the process group and process group id as forked process

    check.pl
    print "process id: $$\n"; my $pid = fork; my $FH; unless($pid){ setpgrp; exec('script'); } print "Child process id is: $pid\n"; while(1) {sleep(5)}
    script file:
    use POSIX; while(1) { sleep(1); print "I am running\n"; my $pid = fork; unless($pid) { while(1) { sleep(2); print "I am child and I'am running\n"; } } }

    In the script file once again fork the process and printing the line

    From another terminal using kill -9 <Negative number of the child process id> command kill all the process belongs to this process group

    The child process is running as a defunct process but the parent process is alive

    Refer the ps command output
    643 15141 9607 0 18:14 pts/1 00:00:00 perl check.pl
    643 15142 15141 0 18:14 pts/1 00:00:00 script <defunct>

    How could I avoid this problem

    Also I need to redirect the script command output and error into one file . How can I achieve it?

      Defunct ("zombie") processes arise when the respective process has terminated, but its (still alive) parent hasn't reaped the child's status by waiting for it.

      When you modify check.pl as follows

      #!/usr/bin/perl use POSIX ":sys_wait_h"; print "process id: $$\n"; my $pid = fork; my $FH; unless($pid){ setpgrp; exec('./script'); } print "Child process id is: $pid\n"; for (1..5) { kill -9, $pid if $_ == 4; # kill children in the 4th round system "ps Tf -o etime,pid,pgrp,stat,cmd"; sleep(3); waitpid(-1, WNOHANG); }

      you'll get something like

      $ ./check.pl process id: 4609 Child process id is: 4610 ELAPSED PID PGRP STAT CMD 06:17 4569 4569 Ss bash 00:00 4609 4609 S+ \_ /usr/bin/perl ./check.pl 00:00 4610 4610 R \_ /usr/bin/perl ./script 00:00 4611 4609 R+ \_ ps Tf -o etime,pid,pgrp,stat,cmd I am running I am running I am child and I'am running I am running ELAPSED PID PGRP STAT CMD 06:20 4569 4569 Ss bash 00:03 4609 4609 S+ \_ /usr/bin/perl ./check.pl 00:03 4610 4610 R \_ /usr/bin/perl ./script 00:02 4612 4610 S | \_ /usr/bin/perl ./script 00:01 4613 4610 S | \_ /usr/bin/perl ./script 00:00 4614 4609 R+ \_ ps Tf -o etime,pid,pgrp,stat,cmd I am child and I'am running I am running I am child and I'am running I am child and I'am running I am running I am child and I'am running I am child and I'am running I am running ELAPSED PID PGRP STAT CMD 06:23 4569 4569 Ss bash 00:06 4609 4609 S+ \_ /usr/bin/perl ./check.pl 00:06 4610 4610 S \_ /usr/bin/perl ./script 00:05 4612 4610 S | \_ /usr/bin/perl ./script 00:04 4613 4610 S | \_ /usr/bin/perl ./script 00:03 4615 4610 S | \_ /usr/bin/perl ./script 00:02 4616 4610 S | \_ /usr/bin/perl ./script 00:01 4617 4610 S | \_ /usr/bin/perl ./script 00:00 4618 4610 S | \_ /usr/bin/perl ./script 00:00 4619 4609 R+ \_ ps Tf -o etime,pid,pgrp,stat,cmd I am child and I'am running I am child and I'am running I am child and I'am running I am running I am child and I'am running I am child and I'am running I am child and I'am running I am running I am child and I'am running I am child and I'am running I am child and I'am running I am child and I'am running I am running ELAPSED PID PGRP STAT CMD 06:26 4569 4569 Ss bash 00:09 4609 4609 S+ \_ /usr/bin/perl ./check.pl 00:09 4610 4610 Z \_ [script] <defunct> 00:00 4623 4609 R+ \_ ps Tf -o etime,pid,pgrp,stat,cmd ELAPSED PID PGRP STAT CMD 06:29 4569 4569 Ss bash 00:12 4609 4609 S+ \_ /usr/bin/perl ./check.pl 00:00 4624 4609 R+ \_ ps Tf -o etime,pid,pgrp,stat,cmd

      As you can see in the next-to-last ps output, all children have been killed, but the script process is defunct, because its parent hasn't yet gotten around to reaping it (due to how I deliberately wrote the loop).  Three secs later, in the last ps output, the process is no longer there, because waitpid has been called in the meantime.