2

perl スクリプト内から tcpdump を使用してキャプチャを実行しようとしています。アイデアは、10000 パケットまたは 10 秒のいずれか早い方をキャプチャすることです。10000 パケットで動作するコードがありますが、キャンセルするために tcpdump にSIGINTorを送信するSIGTERMと、出力が壊れて、スクリプトの残りの部分 (tcpdump の生の出力を処理する) で問題が発生するようです。

関連する perl コード:

    defined(my $pid = fork()) or die "Cannot fork: $!";
    if($pid){
        #parent
        my ($kid,$wait_time) = (0,0);
        do{
            sleep 1;
            $wait_time++;
            $kid = waitpid(-1, WNOHANG);
        }until ($kid > 0 || $wait_time > $MAX_TIME_SEC);

        #kill the child
        if ($kid <= 0){
            kill('SIGTERM',$pid);
        } 
    }else{
        #child runs tcpdump to get raw data and write it to a temporary file
        exec('tcpdump','-ieth1','-s0','-c'.$MAX_PACKETS,'-w'.$dmp_name);
    }

次に起こることは、その tcpdump によって生成されたダンプ ファイルがフィードされ、tshark次のエラーが生成されることです。

tshark: "TheDumpFileFromAbove" がパケットの途中で切断されたようです。

tcpdump の man ページで読んだことから、SIGTERMorを送信するSIGINTと正しく動作するはずです (両方を試しました):

-c フラグを指定して実行すると、SIGINT または SIGTERM シグナルによって中断されるか、指定された数のパケットが処理されるまで、パケットがキャプチャされます。

4

1 に答える 1

1

OK、問題は競合状態であることが判明しました。

kill('SIGTERM',$pid);

これは tcpdump に正常に終了するように指示し、そこで実行することの 1 つは、キャプチャに関する統計 (つまり、パケット数) を書き出すことです。その kill の直後に print ステートメントを配置すると、統計の前に表示される場合もあれば、統計の後に表示される場合もあることに気付きました。したがって、解決策は、tcpdump からの出力を処理する次のコマンドに進む前に、tcpdump が完了するまで待機することです。

waitpid($pid,0);
system('tshark -r dumpcapfile ...')
于 2013-07-29T16:38:22.253 に答える