0

I have the following bash command in which I'm taking a tcpdump and then saving the file using the date command. I want to embed this command directly in my Python script instead of having to call the bash script separately.

#!/bin/bash
timeout 2 tcpdump -i eth1 -s 96 -w /usr/src/pcapFiles/dump$(date +%y%m%d-%H%M%S).pcap

I get the following kind of file names when I run the above script, which is just what I need(i.e. the date and time is rendered in the name):

dump131104-191834.pcap

However, I'm having difficulty in replicating the above command from within Python. I have gotten this far with embedding the command in Python. I'm unsure about how to break the date command so that it can render the file name just like the way I need it. The following is my Python command:

tcpd = subprocess.Popen(["timeout", "2", "tcpdump", "-i", "eth1", "-s", "96", "-w", "/usr/src/pcapFiles/dump$(date +%y%m%d-%H%M%S).pcap"], stdout=subprocess.PIPE)
output, err = tcpd.communicate()

With this command I get the following output file names from tcpdump

dump$(date +%y%m%d-%H%M%S).pcap

Zahaib Akhtar
  • 1,048
  • 1
  • 11
  • 26

1 Answers1

5

$(..), aka command expansion, is performed by the shell. Since you're now using Python instead of a shell, you don't get that feature for free.

The simple fix is to invoke a shell and give it your command:

tcpd = subprocess.Popen(["bash", "-c", "timeout 2 tcpdump -i eth1 -s 96 -w /usr/src/pcapFiles/dump$(date +%y%m%d-%H%M%S).pcap"], stdout=subprocess.PIPE)
output, err = tcpd.communicate()

The arguably more correct fix is to get the current date in Python:

import datetime
filename=datetime.datetime.now().strftime("/usr/src/pcapFiles/dump%y%m%d-%H%M%S.pcap")
tcpd = subprocess.Popen(["timeout", "2", "tcpdump", "-i", "eth1", "-s", "96", "-w", filename, stdout=subprocess.PIPE)
output, err = tcpd.communicate()
that other guy
  • 101,688
  • 11
  • 135
  • 166
  • 2
    You *could* do that, or you could use `datetime` to get the current time: `datetime.datetime.now().strftime('%y%m%d-%H%M%S')` and then substitue that in via normal string substitution. – mgilson Nov 05 '13 at 03:31
  • @Barmar -- `subprocess` is much preferred to `os.popen`. – mgilson Nov 05 '13 at 03:32
  • Yes, this works just fine! @Barmar, Yeah I went through that link as well. Thanks for posting it here. – Zahaib Akhtar Nov 05 '13 at 03:36
  • Go use datetime as suggested by @mgilson. That gives your another controllable and pythonic way to solve things. – Drake Guan Nov 05 '13 at 03:36
  • @Drake Yeah, looking into that as well, I felt that there may be a way of doing this using one of Pythons own functions. Was not aware of putting shell commands in Python. – Zahaib Akhtar Nov 05 '13 at 03:39
  • 1
    Another option is to put `shell=True` while invoking `Popen`. The following info is copied from doc for your reference: If shell is True, the specified command will be executed through the shell. This can be useful if you are using Python primarily for the enhanced control flow it offers over most system shells and still want convenient access to other shell features such as shell pipes, filename wildcards, environment variable expansion, and expansion of ~ to a user’s home directory. http://docs.python.org/2/library/subprocess.html – Drake Guan Nov 05 '13 at 03:43
  • @Drake, yeah I was first calling the Bash script from within Python with the `shell=True` directive, then decided to put it straight into Python. – Zahaib Akhtar Nov 05 '13 at 03:49