14

Im trying to handle tcpdump output in python.

What I need is to run tcpdump (which captures the packets and gives me information) and read the output and process it.

The problem is that tcpdump keeps running forever and I need to read the packet info as soon as it outputs and continue doing it.

I tried looking into subprocess of python and tried calling tcpdump using popen and piping the stdout but it doesnt seem to work.

Any directions on how to proceed with this.

import subprocess

def redirect():
    tcpdump = subprocess.Popen("sudo tcpdump...", stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
    while True:
        s = tcpdump.stdout.readline()
        # do domething with s

redirect()
dsprenkels
  • 1,464
  • 14
  • 21
ashish g
  • 409
  • 1
  • 6
  • 16

2 Answers2

20

You can make tcpdump line-buffered with "-l". Then you can use subprocess to capture the output as it comes out.

import subprocess as sub

p = sub.Popen(('sudo', 'tcpdump', '-l'), stdout=sub.PIPE)
for row in iter(p.stdout.readline, b''):
    print row.rstrip()   # process here
swstephe
  • 1,617
  • 8
  • 16
  • use `for line in iter(p.stdout.readline, b''): print line,` in Python 2 due to ["readahead buffer" bug](http://bugs.python.org/issue3907) – jfs Apr 11 '14 at 21:10
  • `for line in p.stdout:` introduces unnecessary delay in the output on Python 2 (OP wants: *"as soon as it outputs"*). Use `iter(..)` as I've mentioned above. See [Python: read streaming input from subprocess.communicate()](http://stackoverflow.com/a/17698359/4279) – jfs Jun 12 '15 at 19:52
2

By default, pipes are block buffered and interactive output is line buffered. It sounds like you need a line buffered pipe - coming from tcpdump in a subprocess.

In the old days, we'd recommend Dan Bernstein's "pty" program for this kind of thing. Today, it appears that pty hasn't been updated in a long time, but there's a new program called "emtpy" which is more or less the same idea: http://empty.sourceforge.net/

You might try running tcpdump under empty in your subprocess to make tcpdump line buffered even though it's writing to a pipe.

dstromberg
  • 6,356
  • 20
  • 22
  • 1
    python has `pty` module in stdlib. Or `pexpect` could be used. There are also `stdbuf`, `script`, `unbuffer` utilities that may force line-buffered output – jfs Apr 11 '14 at 21:19