henrikbe has asked for the wisdom of the Perl Monks concerning the following question:
Hi all!
I need to execute the process "P" in the background. I suppose I can execute P in the background by saying
system "P &"
or by using fork and exec. However, my perl script need the pid of P in order to communicate with it (P creates logfiles whose names contain P's pid, and the perl script need to read these files). How do I get P's pid? I tried to use fork, but then of course I only got the pid of the new perl process. What I need is the pid of the P process.
Thanks,
Henrik
Re: Executing a process in the background AND getting its pid
by BrowserUk (Patriarch) on Jun 12, 2007 at 07:50 UTC
|
my $pid = open my $fhOut, "| the command ", or die ...;
## or
my $pid = open my $fhIn, "the command |", or die ...;
## or using the 3-arg form on *nix systems
my $pid = open my $fhOut, '|-', "the command ", or die ...;
## or
my $pid = open my $fhIn, '-|', "the command", or die ...;
Or list forms of the latter two, if you need to pass arguments, may make sense on your system.
See open and perlopentut for more information.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
|
Thank you, this seems to work fine!
Henrik
| [reply] |
|
Thanks for your help.
I am having problem getting actual PID of process. Your open command returns the PID which is less than 1 of actual PID.
for ex. PID of my actual process is 1923, i get 1922 which i discovered to be a zombie process.
Can you please tell me what should i do to get the actual process id ?
thanks in advance.
| [reply] |
|
| [reply] |
Re: Executing a process in the background AND getting its pid
by Zaxo (Archbishop) on Jun 12, 2007 at 07:11 UTC
|
my $cpid;
{
defined($cpid = fork) or die $!;
$cpid and last;
# do child stuff and exit.
# exec is good here
}
# parent goes on, knowing $cpid
exec replaces the current program, taking over its pid and never returning.
| [reply] [d/l] |
|
Yes, thank you,
but I don't need to know the pid of the child. The child spawns a new non-perl process (using exec), and it is the pid of this new process I need.
For example, fork starts a new perl process with pid 31238. In this process, exec is called, starting another process with pid 31239. Now my original parent need to know this pid. However, all that is known by the parent is the pid of its child as returned from fork, that is, 31238.
| [reply] |
|
exec replaces the current process with the new process. Especially, this means that the PID will remain the same. If your P command really is a shell script that calls the P executable with some additional parameters, you will need to be more crafty about obtaining the PID. If you have the unix toolset available (and you should, if you're doing fork+exec), then you can look for the PID via the ps program, for example. Maybe you can also have your P process log to STDOUT instead of a logfile and use IPC::Open2 or IPC::Open3 or IPC::Run to monitor the logfile.
| [reply] [d/l] [select] |
|
With exec, the new non-perl program simply takes over the calling process and runs under its pid. If the new program forks again, you could get trouble, but that's the new program's responsibility. You need to know its behavior to use it effectively.
| [reply] |
|
Let's say in another words: You have a Perl program, "A", runs with PID 32237. A forks another process, "B", with PID 31238. So, B is the child process of A. B then exec's another program, "C". Now, C is replacing the process B and using B's PID which is 31238. The original parent, which is "A", needs to know the PID of C. That is 31238. Is it correct?
Consider this:
# /tmp/child-child.pl
print "I'm exec'd: $$\n";
Then in the main program (/tmp/main.pl):
#!/usr/bin/perl
use strict;
use warnings;
print "I'm parent ($0): $$\n";
my $child = fork;
defined $child or die "Can't fork: $!\n";
unless ($child) {
print "I'm child ($0): $$\n";
exec $^X, '/tmp/child-child.pl';
}
The output is:
$ perl /tmp/main.pl
I'm parent (/tmp/main.pl): 12499
I'm child (/tmp/main.pl): 12500
I'm exec'd (/tmp/child-child.pl): 12500
Update: fixed typo
Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!
| [reply] [d/l] [select] |
|
|