2

我正在尝试从 perl 脚本中使用 tcpdump 进行捕获。这个想法是捕获 10000 个数据包或 10 秒,以先到者为准。我有适用于 10000 个数据包的代码,但如果我向 tcpdump 发送SIGINTSIGTERM取消它,输出似乎会损坏,导致脚本的其余部分出现问题(处理 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 的手册页中阅读的内容,发送 aSIGTERMSIGINT应该可以正常工作(我都尝试过):

如果使用 -c 标志运行,它将捕获数据包,直到它被 SIGINT 或 SIGTERM 信号中断或已处理指定数量的数据包。

4

1 回答 1

1

好的,所以问题原来是一个竞争条件:

kill('SIGTERM',$pid);

这告诉 tcpdump 优雅地退出,它在其中所做的一件事就是写出有关捕获的统计信息(即有多少数据包)。我注意到,如果我在杀死之后立即添加打印语句,有时它会出现在统计数据之前,有时会出现在统计数据之后。所以解决方案是等到 tcpdump 完成后再继续执行下一个处理 tcpdump 输出的命令:

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