首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从父命令并行运行两个命令?

如何从父命令并行运行两个命令?
EN

Stack Overflow用户
提问于 2012-01-06 04:30:09
回答 2查看 2.3K关注 0票数 2

我有两个代码

1.

代码语言:javascript
复制
use File::Temp qw(tempfile);
$tmp = new File::Temp( UNLINK => 0 );
system("tv_grab_au | tv_sort >> $file");
system("cp $file $HOME/.xmltv/listings.xml");

unlink($file);

2.

代码语言:javascript
复制
while (-e $file) {
sleep 2;
system("tvtime-command DISPLAY_MESSAGE \'Updating TV Guide. Please wait this might take a several minutes...\'");
}

我想结合这两个代码来运行tv_grab_au xmltv捕获(更新电视指南),同时,发送命令到tvtime显示消息‘更新电视指南。请等待这可能需要几分钟...’,每两秒,直到$file存在。

我试一下这个:

代码语言:javascript
复制
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;
        }
}

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-06 06:16:32

内置的fork函数在一个新的后台进程中创建当前程序的副本。然后,原始进程和“子”进程将同时运行。所以你可以这样做:

代码语言:javascript
复制
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循环将永远不会结束。

内置的waitpid命令可以检查子进程是否仍在运行,并且可以处理子进程异常终止的情况。

代码语言:javascript
复制
# Task 2 
use POSIX ':sys_wait_h';
while (! waitpid $new_pid, &WNOHANG) {   # WNOHANG => non-blocking wait
    print "...";
    sleep 2;
}
票数 4
EN

Stack Overflow用户

发布于 2012-01-06 06:17:22

使用fork()。我添加了额外的sleep()调用,这样您就可以看到进程同时运行和工作。在实践中,crontab更新可能运行得足够快,以至于监视器循环根本不运行,或者只运行一次。我用了“除非(...)”因为在我看来,这样做可以使代码更清晰;要记住的是,fork()将pid返回给父进程,而将零返回给子进程。因此,看不到pid的进程是一个子进程。(如前所述,如果fork失败,则fork将返回undef,并且代码将在原始进程中执行。在我们的例子中,这只是意味着监控在写入完成后启动,所以我们唯一失去的就是监控。)

代码语言:javascript
复制
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";
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8749329

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档