2017-07-13 11 views
1

forkを初めて使用する際に問題があります。フォークを終了して親に戻る

フォークを終了してメインスクリプトに戻るまで、スクリプトは正常に実行されているようです。

代わりに、スクリプトを完全に終了します。

my @files = glob("./input/<Input subnets>.txt") or die "Can't open HostInventory$!";  # Open the Host Inventory csv files for parsing 

foreach my $file (@files) { 

    open (CONFIG, '<', $file) or die "Can't <Input subnets>.txt$!"; 
    my @lines = <CONFIG>; 
    chomp (@lines); 

    $m = scalar @lines/10; 
    for ($m) { 
     s/\..*//g 
    }; 

    for (my $i = 0; $i < @lines; $i += $m) { 

     # take a slice of elements from @files 
     my @lines4 = @lines[$i .. $i + $m]; 

     if (fork() == 0) { 

      for my $n (@lines4) { 
       system("Nmap -dns-servers <IP of DNS server> -sn -v $n -oX ./input/ip360_DNS/ip360_DNS$n.xml --send-eth --reason"); 
      } 

      exit; 
     } 
    } 

    wait for 0 .. @lines/$m; 
} 

この時点では、親スクリプトで続行し、スキャンの出力を解析するサブルーチンを開く必要があります。代わりに、スクリプトを完全に終了します。

私は間違っていますか?

- = - = - = - = 私は以下のParallel :: ForkManagerの例を試しました。スタンドアロンプ​​ロセスとして実行すると、完全に機能します。私はサブルーチンの中でコードを実行していますが、私がそれを試みると、Perlインタプリタがクラッシュします。提案?

#1/usr/bin/perl -w 

use Parallel::ForkManager; 
use strict;            # Best Practice 
use warnings;           # Best Practice 
use Getopt::Long;          # Add the ability to use command line options 

if ([email protected]) { 
    &help; 
    exit 1 
} 

GetOptions(
    full =>     \&full, 
    temp =>     \&temp, 
); 

       ####################################################################### 
       ####################################################################### 
       #                  # 
       #      Call each function        # 
       #                  # 
       ####################################################################### 
       ####################################################################### 

sub temp { 
    &speak; 
    &simple; 
    &speak2; 
    exit; 
} 

sub full { 
    &speak; 
    &simple; 
    &speak2; 
    exit; 
} 

sub speak { 
    print "This is where I wait for 2 seconds\n"; 
    sleep (2); 
} 

my $process = $$; 
print "$process\n"; 

sub simple { 

    my $pm = new Parallel::ForkManager(10); 
    $pm->run_on_finish(
    sub { $process; 
     print "** PID $process\n"; 
     } 
    ); 

    my @files = glob("./ping.txt") or die "Can't open CMS HostInventory$!";  # Open the CMS Host Inventory csv files for parsing 
    foreach my $file (@files){ 
     open (CONFIG, '<', $file) or die "Can't ip360_DNS File$!"; 
     my @lines = <CONFIG>; 
     chomp (@lines); 

     foreach my $n (@lines) { 
      # Forks and returns the pid for the child: 
      my $pid = $pm->start and next; 

      # ... do some work with $data in the child process ... 
      system("ping $n >> ./input/$n.txt"); 

     } 
     $pm->finish; # Terminates the child process 
    } 
} 

sub speak2 { 
    print "In new subroutine\n"; 
} 
+3

Parallel :: ForkManagerはあなたの人生を少し楽にします。 – ikegami

+5

'fork()'は元のものとまったく同じ第2のプロセスを作成します。オリジナルはコピーと同様に動作し続けます。分岐したプロセスからの「リターン」はありません。 –

+0

@ジム・ギャリソン、彼らは文字通り「リターン」という言葉を使用していません。彼らは、親が子どもたちが完了するのを待ってから、別のコードを進めることを望みます。 – ikegami

答えて

5

まず、スクリプトは「完全に終了しません」。子供たちが終わるのを待つ。または少なくともそれらのいくつか。あなたの計算はちょっとです。


最後の要素をスキップしています。

$m = scalar @lines/10; 
for ($m) {s/\..*//g}; 

use POSIX qw(floor); 

my $m = floor(@lines/10); 

と同等ですが、それはあなたが二度境界要素を実行している

use POSIX qw(ceil); 

my $m = ceil(@lines/10); 

でなければなりません。

my @lines4 = @lines[$i .. $i + $m]; 

my @lines4 = @lines[$i .. $i + $m - 1]; 

wait for 0 .. @lines/$m; 

use POSIX qw(ceil); 

wait for 1 .. ceil(@lines/$m); 

か、単に

1 while wait > 0; 
する必要がありますする必要があります

使いやすいParallel::ForkManager

use Parallel::ForkManager qw(); 

my $pm = Parallel::ForkManager->new(10); # Max number of children at a time. 

$pm->run_on_finish(sub { 
    my ($pid, $exit, $id, $signaled, $dumped, $data) = @_; 
    my ($config_qfn, $target) = @$id; 
    ... 
}); 

for my $config_qfn (glob(...)) { 
    open(my $config_fh, '<', $config_qfn) 
     or die("Can't open \"$config_qfn\": $!\n"); 

    chomp(my @targets = <$config_fh>); 

    for my $target (@targets) { 
     my $pid = $pm->start([$config_qfn, $target]) 
      and next; 

     exec(...) 
      or die("exec: $!"); 
    } 
} 

$pm->wait_all_children(); 

ところで、私はバッチで物事をやめたことに気づいたかもしれません。これにより、systemの代わりにexecを使用することができました。これにより、バッチごとにフォーク数が1つ減らされ、バッチを使用しない方が効率的になりました。

+0

上記のParallel :: ForkManagerの例を試しました。スタンドアロンプ​​ロセスとして実行すると、完全に機能します。私はサブルーチンの中でコードを実行していますが、私がそれを試みると、Perlインタプリタがクラッシュします。提案? – ohm

+0

「クラッシュ」とはどういう意味ですか?あなたはWindowsにいますか? – ikegami

+0

はい、私はWindows上です。 – ohm

関連する問題