我正在 Python 中运行tcpdump
,我想知道有多少数据包 被内核删除。
在命令行上运行时,tcpdump如下所示:
me@mypc:$ sudo tcpdump -w myPackets.cap -i eth0 ip
tcpdump: listening on eth2, link-type EN10MB (Ethernet), capture size 65535 bytes
^C28 packets captured
28 packets received by filter
0 packets dropped by kernel
这就是我在Python脚本中调用tcpdump
的方法:
f_out = open("tcpdumpSTDOUT", "w")
f_err = open("tcpdumpSTDERR", "w")
tcpdumpProcess = subprocess.Popen(['tcpdump',
'-w', 'myPackets.cap', '-i', 'eth0', '-n','ip'],
stdout=f_out,
stderr=f_err)
# a few seconds later:
tcpdumpProcess.kill()
f_in.close()
f_out.close()
现在,如果我查看tcpdumpSTDERR
,我仅会看到通常的第一个输出行:
tcpdump:侦听eth0,链接类型EN10MB(以太网),捕获大小 65535字节
其余的都在哪里?
修改 我尝试了另一种方法:
>>> myProcess = subprocess.Popen("tcpdump -w myPackets.cap -i eth2 ip", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> myProcess.communicate()
然后我从另一个shell中杀死了tcpdump,并显示了commnunicate()的输出:
('', 'tcpdump: listening on eth2, link-type EN10MB (Ethernet), capture size 65535 bytes\n')
......仍然只是第一行!
编辑2 有趣的是:
>>> import shlex
>>> a = subprocess.Popen(shlex.split("tcpdump -w myPackets.cap -i eth2 ip"), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> a.terminate()
>>> a.communicate()
('', 'tcpdump: listening on eth2, link-type EN10MB (Ethernet), capture size 65535 bytes\n221 packets captured\n221 packets received by filter\n0 packets dropped by kernel\n')
答案 0 :(得分:1)
使用proc.terminate()
代替proc.kill()
:
import shlex
import subprocess
import time
with open("tcpdumpSTDERR", "wb") as f_err: # close the file automatically
proc = subprocess.Popen(shlex.split("tcpdump -w myPackets.cap -i eth2 ip"),
stderr=f_err)
time.sleep(2) # wait a few seconds
proc.terminate() # send SIGTERM instead of SIGKILL
proc.wait() # avoid zombies
答案 1 :(得分:1)
问题是我在流程上调用kill()
而不是terminate()
。对于后者,所有消息都存储在我指定为stderr
的任何内容中(tcpdump,由于某种原因,写入stderr而不是stdout)。
所以,如果它可以帮助其他人,我决定将stderr重定向到subprocess.PIPE
并直接在Python中解析字符串:
>>> tcpdumpProcess = subprocess.Popen(['tcpdump',
'-w', 'myPackets.cap', '-i', 'eth0', '-n','ip'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
>>> tcpdumpProcess.terminate()
# stdout in [0], stderr in [1]
>>> tcpdump_stderr = tcpdumpProcess.communicate()[1]
>>> print tcpdump_stderr
tcpdump: listening on eth2, link-type EN10MB (Ethernet), capture size 65535 bytes
40 packets captured
40 packets received by filter
0 packets dropped by kernel