2017-02-24 10 views
0

スレッドを使用してPerlスクリプトで問題が発生しました。マルチスレッドPerlスクリプトとcrontab/initスクリプト

Perlがアクティブスレッドで終了しました::

0 running and unjoined 
    1 finished and unjoined 
    0 running and detached 

変数PATHSHELL変数で正しい

それは私がそれを手動で起動しますが、私はそれがcrontabファイルを使用して起動したとき、私はこのフィードバックを持っていたときに正常に動作しますcrontad。

私は、initスクリプト(サービスとして起動するように)と同じエラーをしよう:

Feb 24 08:04:48 SERVER kernel: perl[103293]: segfault at 4a8 ip 00007f6cfd075dd9 sp 00007fffb93437c0 error 4 in libperl.so[7f6cfcfdf000+183000] Feb 24 08:04:49 SERVER test_ping[102238]: Perl exited with active threads: Feb 24 08:04:49 SERVER test_ping[102238]: 0 running and unjoined Feb 24 08:04:49 SERVER test_ping[102238]: 1 finished and unjoined Feb 24 08:04:49 SERVER test_ping[102238]: 0 running and detached

だから私はまたして修正のperlに試してみました:

for my $thread (threads->list) {                             
$thread->join();                    
} 

代わりの

for my $thread (threads->list) {                             
$thread->detach();                    
} 

この変更後、手動でスクリプトを起動すると、このスクリプトが停止またはフリーズしているようです。だから、これを再開する

はすべて私のチェックです:

それが動作しないのcrontab経由
  • を働く手動で実行
    1. 、PATH変数とSHELL 変数のチェックはinitスクリプト経由
    2. OKです、動作しません
    3. すべてのスレッドに参加するようにperlスクリプトを修正しようとしましたが、それ以降はスクリプト がフリーズしています。

    誰かが提案していますか?チェック/実行する何か?

    THK

    プロセスfonction以下
    use lib '/usr/local/perf/lib'; 
    use lib '/usr/share/perl5'; 
    use threads; 
    use Thread::Queue; 
    use SNMP::Persist qw(&define_oid &start_persister &define_subtree); 
    use Schedule::ByClock; 
    use Time::HiRes qw(usleep ualarm gettimeofday tv_interval); 
    
    use strict; 
    #use warnings; 
    use constant DEBUG => 0; 
    use constant DEBUG2 => 1; 
    
    if ($#ARGV + 1 != 2) { 
    print "usage: test_ping.pl OUTPUTFILE INPUTFILE \n"; 
    exit; 
    } 
    
    my $output_file=$ARGV[0]; 
    my $data_file=$ARGV[1]; 
    shift @ARGV; 
    shift @ARGV; 
    
    #start the thread serving answers 
    start_persister(); 
    
    #create queue for processing commands 
    my $q_queue = new Thread::Queue; 
    my $r_queue = new Thread::Queue; 
    
    #create threads for processing queues 
    for(my $i= 0; $i < $thread_num; $i++) { 
         threads->create(\&process) -> detach(); 
    } 
         my $datestring=localtime(); 
    
         my %subtree; 
         my @raw_data; 
    
         my ($q_line, @q_split); 
         my ($r_line, @r_split); 
         my $index=0; 
    
         # open file to get data 
         open(DAT, $data_file) || die("Could not open file!"); 
         @raw_data=<DAT>; 
         close(DAT); 
    
         # enqueue all lines to be process by threads 
         foreach $q_line (@raw_data) { 
           chomp($q_line); 
           $q_line =~ s/^\s+//; 
           $q_line =~ s/\s+$//; 
           next if ($q_line =~ /^#.*/); 
           next if ($q_line eq ""); 
           next if ($q_line =~ /^\|/); 
    
           @q_split=split(/\|/,$q_line); 
           next if (!($q_split[0] eq "icmp" || $q_split[0] eq "tcp" || $q_split[0] eq "ldap" || $q_split[0] eq "dig")); 
    
           $q_queue->enqueue(++$index ."|". $q_line); 
         } 
    
         while ($index != 0 && ($r_line = $r_queue->dequeue)) { 
    
           open(my $fh, '>>', $output_file) or die "Could not open file '$output_file' $!"; 
           print $fh $datestring."|"; 
           print $fh $r_line."\n"; 
           close $fh; 
           @r_split=split(/\|/,$r_line); 
           $index--; 
         } 
    
         for my $thread (threads->list) {                             
          $thread->detach();                    
        } 
    

    :すべての

    sub process { 
        # my @hotefqdn = split(/\./, `hostname`); 
        # my $hote=$hotefqdn[0]; 
        my ($q_line,@q_split,$q_index,$q_query); 
        my ($q_module,$q_type,$q_name,$q_host,$q_port,$q_ssl,$q_send,$q_expect,$q_quit); 
        my ($q_lookup,$q_record); 
        my ($q_base_dn,$q_attr,$q_binddn,$q_password,$q_warn_time,$q_crit_time,$q_timeout); 
        my ($r_tab); 
    
        while ($q_line = $q_queue->dequeue) { 
    
          @q_split=split(/\|/,$q_line); 
    
          $q_index=$q_split[0]; 
          $q_module=$q_split[1]; 
    
          if ($q_module eq "icmp") { 
            $q_type=$q_split[2]; 
            $q_name=$q_split[3]; 
            $q_host=$q_split[4]; 
            $q_query="$q_host (ping)"; 
            print "query=$q_query\n" if(DEBUG); 
            $r_tab=icmp_query($q_host); 
          } 
          elsif ($q_module eq "tcp") { 
            $q_type=$q_split[2]; 
            $q_name=$q_split[3]; 
            $q_query="$q_host ($q_type:$q_port)"; 
            print "query=$q_query\n" if(DEBUG); 
            $r_tab=tcp_query($q_host,$q_port,$q_ssl,$q_send,$q_expect,$q_quit); 
          } 
          elsif ($q_module eq "ldap") { 
            $q_type=$q_split[2]; 
            $q_name=$q_split[3]; 
            print "query=$q_query\n" if(DEBUG); 
            $r_tab=ldap_query($q_host,$q_base_dn,$q_port,$q_attr,$q_binddn,$q_password,$q_warn_time,$q_crit_time,$q_timeout); 
          } 
          elsif ($q_module eq "dig") { 
            $q_type=$q_split[2]; 
            $q_name=$q_split[3]; 
            $q_query="$q_lookup($q_record) @".$q_host; 
            print "query=$q_query\n" if(DEBUG); 
            $r_tab=dig_query($q_host,$q_port,$q_lookup,$q_record,$q_expect); 
          } 
    
          $r_queue->enqueue($q_index."|".$q_name."|".$q_type."|".$q_query."|".$r_tab->{'min'}."|".$r_tab->{'med'}."|".$r_tab->{'avg'}."|".$r_tab->{'max'}."|".$r_tab->{'dev'}."|".$r_tab->{'loss'}."|".$r_tab->{'err'}); 
        } 
    

    }

  • +0

    あなたが持っている問題を再現する最小限のコンパイル可能なコードスニペットを考え出すことができれば、本当に役に立ちます。 – Tanktalus

    +0

    それで、私はまだ問題を再現している最小のスニペットを求めました。問題はおそらくコードと関係しているからです。 – Tanktalus

    答えて

    1

    まず、あなたのスレッドをデタッチしないでください。あなたがそうするとき、あなたは彼らが終わるのを待つことができません。なぜ、あなたのスレッドが終了しない:

    for (my $i= 0; $i < $thread_num; $i++) { 
        threads->create(\&process) -> detach(); 
    } 
    
    ... 
    
    for my $thread (threads->list) { 
        $thread->detach(); 
    } 
    

    は質問に今

    for (1..$thread_num) { 
        threads->create(\&process); 
    } 
    
    ... 
    
    ... Tell the threads to finish up ... 
    
    for my $thread (threads->list) { 
        $thread->join(); 
    } 
    

    すべきですか?まあ、あなたは決して退室するように言わないので、彼らは決してしません!あなたは終了し、それらに依頼する必要があり、それは以下を添加することによって達成することができます。

    $q_queue->end(); 
    

    どのような次はあなたが上記の修正を適用した後、あなたが得るものです。私はまた、スレッドに関連するコードをprocessから外しました。そこには属していません。最後に、出力コードを独自のスレッドに移動して、$indexの依存関係を削除しました。

    sub process { 
        my ($q_line) = @_; 
        ... 
        return join("|", $q_index, $q_name, $q_type, $q_query, @$r_tab{qw(min med avg max dev loss err)}); 
    } 
    
    my $request_q = Thread::Queue->new(); 
    my $response_q = Thread::Queue->new(); 
    
    my @worker_threads; 
    for (1..$thread_num) { 
        push @worker_threads, async { 
         while (defined(my $request = $request_q->dequeue())) { 
         $response_q->enqueue(process($request)); 
         } 
        }; 
    } 
    
    my $output_thread = do { 
        my $datestring = localtime(); 
    
        open(my $fh, '>', $output_file) 
         or die("Can't create file \"$output_file\": $!\n"); 
    
        async { 
         while (defined(my $response = $response_q->dequeue())) { 
         print($fh "$datestring|$response\n"); 
         } 
        } 
    }; 
    
    {  
        my %protos = map { $_ => 1 } qw(icmp tcp ldap dig); 
    
        open(my $fh, '<', $data_file) 
         or die("Can't open file \"$data_file\": $!\n"); 
    
        my $index = 0; 
        while (<$fh>) { 
         s/^\s+//; 
         s/\s+\z//; 
         next if $_ eq "" || /^#/; 
    
         my ($proto) = split /\|/; 
         next if !$protos{$proto}; 
    
         $request_q->enqueue(++$index ."|". $_); 
        } 
    } 
    
    $request_q->end(); 
    $_->join() for @worker_threads; 
    
    $response_q->end(); 
    $output_threads->join(); 
    
    +0

    私はすでにこの修正を行っており、悪化しています。手動で起動すると、スクリプトは機能しません。 [root @ SERVER]#./test_ping.sh <ここにこだわって、再度プロンプトにアクセスできません> – elbrabra94

    +0

    @ elbrabra94もう一度、 'process'が返されない理由を尋ねてきましたが、プロセスを表示しない。私は尋ねなかった問題だけを解決することができます。 – ikegami

    +0

    申し訳ありません私のメインポストにプロセス機能を追加しました – elbrabra94

    関連する問題