Perl 如何从父命令并行运行两个命令?
我有两个密码 一, 二, 我想结合这2段代码来运行tv_grab_xmltv grabber(更新电视指南),同时向tvtime发送命令以显示消息“更新电视指南”。请等待,这可能需要几分钟…,每两秒一次,直到$file存在 我试试这个:Perl 如何从父命令并行运行两个命令?,perl,Perl,我有两个密码 一, 二, 我想结合这2段代码来运行tv_grab_xmltv grabber(更新电视指南),同时向tvtime发送命令以显示消息“更新电视指南”。请等待,这可能需要几分钟…,每两秒一次,直到$file存在 我试试这个: use strict; use warnings; use File::Temp qw(tempfile); my $file = new File::Temp( UNLINK => 0 ); use POSIX qw(:sys_wait_h); $|++
use strict;
use warnings;
use File::Temp qw(tempfile);
my $file = new File::Temp( UNLINK => 0 );
use POSIX qw(:sys_wait_h);
$|++;
defined(my $pid = fork) or die "Couldn't fork: $!";
if (!$pid) {
system("tv_grab_huro | tv_sort >> $file");
unlink($file);
}
else {
while (! waitpid($pid, WNOHANG)) {
system("tvtime-command DISPLAY_MESSAGE \'Updating TV Guide. Please wait this might take a several minutes...\'");
sleep 2;
}
}
谢谢。内置函数将在新的后台进程中创建当前程序的副本。原始进程和“子”进程将同时运行。因此,您可以执行以下操作:
use File::Temp qw(tempfile);
my $file = new File::Temp( UNLINK => 0 );
my $new_pid = fork();
die "fork failed $!" unless defined $new_pid; # this is uncommon
# Task 1 - in the background
if ($new_pid == 0) {
system("tv_grab_au | tv_sort >> $file");
system("cp $file $HOME/.xmltv/listings.xml");
unlink($file);
exit; # don't forget this part!
}
# Task 2 - in the foreground
while (-e $file) {
print "...";
sleep 2;
}
使用
$file
作为第一个任务何时完成的指示器有一些缺点。如果子代码有运行时错误怎么办?如果子进程被中断怎么办?子进程可能在有机会删除$file
之前退出。那么父进程中的while
循环将永远不会结束
内置命令可以检查子进程是否仍在运行,并可以处理子进程异常终止的情况
# Task 2
use POSIX ':sys_wait_h';
while (! waitpid $new_pid, &WNOHANG) { # WNOHANG => non-blocking wait
print "...";
sleep 2;
}
使用fork()。我添加了额外的sleep()调用,以便您可以看到进程同时运行和工作。实际上,crontab更新可能运行得足够快,以至于监视器循环根本不运行,或者只运行一次。我使用“除非(…)”是因为在我看来,它使代码更清晰;需要记住的是,fork()将pid返回给父对象,将零返回给子对象。因此,没有看到pid的流程是一个子流程。(正如已经指出的,如果fork失败,fork将返回undef,代码将在原始进程中执行。在我们的例子中,这只意味着在写入完成后启动监控,因此我们唯一失去的就是监控。)
my$file=“/tmp/$$.crontab.txt”;
my$crontab=fork
将“0”返回给子级。如果fork失败,它只返回undef
。
use File::Temp qw(tempfile);
my $file = new File::Temp( UNLINK => 0 );
my $new_pid = fork();
die "fork failed $!" unless defined $new_pid; # this is uncommon
# Task 1 - in the background
if ($new_pid == 0) {
system("tv_grab_au | tv_sort >> $file");
system("cp $file $HOME/.xmltv/listings.xml");
unlink($file);
exit; # don't forget this part!
}
# Task 2 - in the foreground
while (-e $file) {
print "...";
sleep 2;
}
# Task 2
use POSIX ':sys_wait_h';
while (! waitpid $new_pid, &WNOHANG) { # WNOHANG => non-blocking wait
print "...";
sleep 2;
}
my $file = "/tmp/.$$.crontab.txt";
my $crontab = <<EOS;
# Crontab lines here. Inserted at @{[scalar localtime()]}
EOS
my ($writer_pid, $monitor_pid);
$|++;
# Open file BEFORE launching processes. The monitor depends on the file's
# presence or absence, so if we opened it in the writer process, there'd be a
# chance the monitor process would check before we created it, and exit without
# monitoring.
die "Cannot open temp file\n" unless open(WRITE, ">" . $file);
# Crontab file handle gets passed to the forked process, so we can just use it.
# Altered so we can see the process do its thing.
unless ($writer_pid = fork()) {
print WRITE $crontab."\n";
close WRITE;
print("crontab -l |grep -v backup >> $file");
sleep 20;
print("crontab $file");
sleep 10;
unlink($file);
print "done!\n";
exit;
}
# Either file will exist, or the previous process will
# have completed. If it exists, we monitor. If not,
# we exit immediately.
unless ($monitor_pid = fork()) {
# Child: monitor the writer.
my $waitcount = 1;
while ( -e $file ) {
sleep 2;
print "($waitcount) installing crontab...";
$waitcount++;
}
print "installed\n";
exit;
}
waitpid($monitor_pid, 0);
waitpid($writer_pid,0);
print "both processes done\n";