I've got a Perl script that starts a background job to print some logging information into a file, executes something, and then finishes.
I would like to end the background process when the script is done,
but as far as I know, if I use a double fork as below, then waitpid($pid,0)
will wait for the background process to finish, instead of killing it,
and kill(9,$pid)
won't get rid of the background process.
Example script:
#!/usr/bin/perl
use strict;
# Do a first general top
my $ret = `top -b -n 1 > logfile`;
# Do a background $USER top every minute
my $cmd = "top -b -d 60 -n 300 -u $ENV{USER} >> logfile";
my $pid;
unless ($pid = fork) {
unless (fork) { #second_fork
exec "$cmd";
die "exec failed!";
} #second_fork
exit 0;
}
# Script does something else for 1-2 hours
# [...]
# We are finished now, let's finish the logging
# waitpid($pid,0) would wait until top command is finished
force_background_job_to_finish($pid) if (background_job_still_running($pid));
# Add final top to the end
$ret = `top -b -n 1 >> logfile`;
1;
Any ideas how to force_background_job_to_finish
?
This works for me:
$SIG{CHLD}="IGNORE";
my $cmd = "top -b -d 60 -n 300 -u $ENV{USER} >> logfile";
if (my $logger_pid=fork) {
# parent
do_something_for_1to2_hours();
kill 15, $logger_pid;
} else {
# child (logger)
exec($cmd);
}
Usually double fork is used so that you don't have to worry about reaping child processes. Since you want to control the child process, you can just do a single fork, which will give you the process id which you can then use to kill your child process using kill.
来源:https://stackoverflow.com/questions/19029855/perl-run-background-job-and-force-job-to-finish