Gnowl Gnowl - 10 months ago 54
Python Question

using subprocess Popen with multiple quoted arguments

i'm trying to use python's subprocess to execute a couple of commands in gdb non-interactively. The equivalent command i'd execute in the shell would be:

gdb - 9833 -ex "set someval=50" -ex "p someval" --batch

and it would i would get the following output:

[Thread debugging using libthread_db enabled]
[New Thread 0x2b6c64f09dc0 (LWP 9833)]
[New Thread 0x549ec940 (LWP 12128)]
[New Thread 0x585f2940 (LWP 12127)]
: ...
0x0000003670407655 in pthread_join () from /lib64/
$1 = 50

That's all well and good, but when i try to script it in python to get the same output, the gdb arguments don't get executed. I'm using cmdline args to fill in the command string, and i see gdb attaching to the pid, when i print the output, but i don't see the gdb print output, and neither is the set performed.
Here's my script:

cmd = ['gdb','-',pid,'-ex','"set ' + sys.argv[2] + '=' + sys.argv[3] + '"','-ex','"p ' + sys.argv[2] + '"','--batch']
print cmd
result = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()
print result

What am i missing?

Answer Source

You've got too many quotes. If you have a shell command that looks like this:

echo "this is a test"

The equivalent call to subprocess.Popen is:

subprocess.Popen(['echo', 'this is a test'])

That's a command of two elements, and just like in the shell command the second argument contains whitespace.

With that in mind, this:

gdb - 9833 -ex "set someval=50" -ex "p someval" --batch

Becomes something like this:

cmd = ['gdb','-',pid,
       '-ex','set ' + sys.argv[2] + '=' + sys.argv[3],
       '-ex','p ' + sys.argv[2],

Although I think this is a slightly more clear way of getting to the same place:

cmd = ['gdb','-',pid,
       '-ex', 'set {}={}'.format(sys.argv[2], sys.argv[3]),
       '-ex', 'p {}'.format(sys.argv[2]),