1

I would like to run tcpdump from python for x amount of minutes specified from the user. At the moment my function looks like this:

def tcpdump():
    run_time = int(input("\nHow many minutes would you like the bash to run?\n"))

    time_to_end = time.time() + 60 * run_time

    print("\ntcpdump running...\n")

    while time.time() < time_to_end:
        p = subprocess.Popen("./tcpdump.bash", shell=True) 
    p.terminate()

However this seems to repeatedly launch tcpdump as I get the following output:

tcpdump: (all BPF devices are busy)
tcpdump: (all BPF devices are busy)
tcpdump: (all BPF devices are busy)

I am not sure how to solve this, and additionally I am not sure how to kill the process, as p.kill() doesnt seem to work.

----------------- EDITED ---------------------

I have now tried the following, however I am not sure if my subprocess gets killed correctly or if it will run infinitely at the background:

def tcpdump:
    run_time = int(input("\nHow many minutes would you like to collect benign data?\n"))

    time_to_end = time.time() + 60 * run_time

    print("\ntcpdump running...\n")

    p = subprocess.Popen(['tcpdump', '-i', 'en0', '-w', 'test.pcap']))
    while time.time() < time_to_end:
          p.communicate()
    p.kill()
user3755632
  • 381
  • 1
  • 2
  • 20
  • Read about [threading.Timer](https://docs.python.org/3/library/threading.html#threading.Timer) to **run a function after interval seconds** to `kill` the `subprocess`. – stovfl Jan 13 '19 at 19:09
  • You can just use bash's timeout builtin `timeout 300 tcpdump ...` – hek2mgl Jan 13 '19 at 19:43
  • Bash doesn't do anything useful here at all. See https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess – tripleee Jan 13 '19 at 19:52
  • I tried calling tcpdump directly from python as you @trippleee are suggesting but I had many errors. – user3755632 Jan 13 '19 at 20:00

1 Answers1

1

You have the timing sorted but the problem is that everytime that while loop runs it's going to popen again and spawn a new process.

Rather do it like this:

import threading
import subprocess

def tcpdump():
    print("\ntcpdump running...\n")
    p = subprocess.Popen("./tcpdump.bash", shell=True)
    p.wait()

run_time = int(input("\nHow many minutes would you like the bash to run?\n"))
t = threading.Thread(target=tcpdump, daemon=True)
t.start()
t.join(run_time * 60)

The tcpdump function now just opens a process and waits for it to close. The main code uses the Threading.join function with a time out specified. Once the timeout has elasped the child thread is killed and control is returned back to the parent.

testfile
  • 2,145
  • 1
  • 12
  • 31