2012-01-05 17 views
2

は私が持っている2つのコード親から2つのコマンドを並列に実行するにはどうすればよいですか?

1.

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.

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グラバ(更新TVガイド)を実行するには、この2のコードを組み合わせて、したいと思います

、 TVガイドの更新メッセージを表示するには、tvtimeにコマンドを送信します。 $ fileが存在するまで、2秒おきに、これは数分かかるかもしれません... '

私はこの1つを試してみてください。

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; 
     } 
} 

感謝。

答えて

4

組み込み関数forkは、現在のプログラムのコピーを新しいバックグラウンドプロセスに作成します。元のプロセスと「子プロセス」は同時に実行されます。最初のタスクは、いくつかの欠点を持って終了したときの指標として$fileを使用して

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を削除する機会を得る前に終了できます。親プロセスのwhileループは終了しません。

組み込みのwaitpidコマンドは、子プロセスがまだ実行中かどうかをチェックし、子プロセスが異常終了した場合に対応できます。

# Task 2 
use POSIX ':sys_wait_h'; 
while (! waitpid $new_pid, &WNOHANG) { # WNOHANG => non-blocking wait 
    print "..."; 
    sleep 2; 
} 
0

fork()を使用します。余分なsleep()呼び出しを追加して、プロセスが実行され、動作することを確認できます。実際には、crontabの更新は、おそらくモニターループがまったく実行されないか、または1回だけ実行されるほど速く実行されます。私はコードをもっとはっきりさせるように思えるので、 "を除いて(...)"を使いました。覚えておくべきことは、fork()がpidを親に返し、ゼロを子に返すということです。したがって、pidが表示されないプロセスはサブプロセスです。フォークが失敗した場合、フォークはundefを返し、コードは元のプロセスで実行されます。私たちのケースでは、これは単に、書き込みが終了した後にモニタリングが開始されることを意味するため、私たちが負うものは監視です)。

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

'fork'は子に「0」を返します。フォークが失敗した場合にのみ 'undef'を返します。 – mob

+0

あなたは正しいです、私はその編集を行います。 –

関連する問題