0

Pythontcpdump内から実行していますが、カーネルによってドロップされたパケット数を知りたいです。

コマンド ラインで実行すると、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()

次に、別のシェルから tcpdump を強制終了すると、commnunicate() の出力が表示されました。

('', 'tcpdump: listening on eth2, link-type EN10MB (Ethernet), capture size 65535 bytes\n')

...まだ最初の行のみです!

EDIT 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 は、何らかの理由で、stdout ではなく stderr に書き込みます)。

したがって、他の人に役立つかもしれない場合に備えて、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 に答える