我正在尝试使用perl脚本中的tcpdump进行捕获。这个想法是捕获10000个数据包或10秒,以先到者为准。我的代码适用于10000个数据包,但是如果我向tcpdump发送SIGINT
或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手册页中的内容,发送SIGTERM
或SIGINT
应该正常工作(我已经尝试过):
如果使用-c标志运行,它将捕获数据包,直到它为止 被SIGINT或SIGTERM信号或指定数量的信号中断 数据包已被处理。
答案 0 :(得分:0)
好的,所以问题结果是竞争条件:
kill('SIGTERM',$pid);
告诉tcpdump正常退出,其中的一件事就是写出有关捕获的统计信息(即有多少数据包)。我注意到,如果我在杀戮之后立即发出一个印刷声明,有时它会在统计数据之前出现,有时候会出现。所以解决方案是等到tcpdump完成后继续执行下一个处理tcpdump输出的命令:
waitpid($pid,0);
system('tshark -r dumpcapfile ...')