Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python with tcpdump in a subprocess: how to close subprocess properly?

I have a Python script to capture network traffic with tcpdump in a subprocess:

p = subprocess.Popen(['tcpdump', '-I', '-i', 'en1',
                  '-w', 'cap.pcap'], stdout=subprocess.PIPE)
time.sleep(10)
p.kill()

When this script completes its work, I'm trying to open output .pcap file in Wireshark and getting this error:

"The capture file appears to have been cut short in the middle of a packet."

What solution could be applied for "proper" closing of tcpdump's subprocess?

like image 641
olpo.graphy Avatar asked Oct 19 '16 19:10

olpo.graphy


3 Answers

Instead of p.kill(), you can use p.send_signal(subprocess.signal.SIGTERM) to send a terminate signal rather than a kill (p.terminate() does the same).

The Popen docs describe the send_signal() command. The documentation on signals is a bit weak, but a dir(subprocess.signal) will list all the signals you may send to the process, but terminate should allow it some time to clean up.

like image 181
rkh Avatar answered Nov 07 '22 14:11

rkh


Found working solution:
I've changed p.kill() to p.terminate().
After this change the subprocess is "properly" finished (output of tcpdump subprocess with statistics available in console) and output .pcap file not damaged.

like image 21
olpo.graphy Avatar answered Nov 07 '22 15:11

olpo.graphy


I had the same problem about closing subprocesses. This thread really helped, so thanks, especially to https://stackoverflow.com/users/3583715/rkh. My solution:

Before:

output = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
message = output.stdout.read()
output.stdout.close()

After reading the Popen docs:

output = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
message = output.stdout.read()
output.TerminateProcess()

For some reason, calling output.kill(), and/or output.terminate() or sending output.send_signal(subprocess.signal.SIGTERM) didn't work, but output.TerminateProcess() did.

like image 44
jsamsf Avatar answered Nov 07 '22 15:11

jsamsf