0

tcpdumpPython中运行,我想知道内核丢弃了多少数据

在命令行上运行时,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

这就是我tcpdump在 Python 脚本中调用的方式:

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')
4

2 回答 2

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
于 2013-07-17T10:15:10.513 回答
1

问题是我调用kill()了进程而不是terminate(). 对于后者,所有消息都存储在我指定的任何内容中stderr(tcpdump,出于某种原因,写入标准错误而不是标准输出)。

因此,如果它可能对其他人有所帮助,我决定将 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
于 2013-07-17T10:15:49.457 回答