0

This is a bash command that I run in python and get the expected result:

count = subprocess.Popen("ps -ef | grep app | wc -l", stdout=subprocess.PIPE, shell=True)

but when I'd like to pass an argument (count in this case) cannot figure out how to do it. I tried:

pid = subprocess.call("ps -ef | grep app | awk -v n=' + str(count), 'NR==n | awk \'{print $2}\'", shell=True)

and

args = shlex.split('ps -ef | grep app | awk -v n=' + str(count), 'NR==n | awk \'{print $2}\'')
pid = subprocess.Popen(args, stdout=subprocess.PIPE, shell=True)

among other attempts, from various posts here, but still cannot make it.

jimakos17
  • 857
  • 3
  • 14
  • 30
  • 1
    Because you're terminating your string with `' + str(..)` rather than with `" + str(...)`. And on the second attempt you pass a colon as such `, 'NR==` for whatever reason. Your syntax is all over the place. – Torxed May 30 '16 at 09:13

3 Answers3

2

You're mixing opening and closing quotations and you pass a colon by mistake on your other attempts among other things.

Try this for a fix:

pid = subprocess.call("ps -ef | grep app | awk -v n=" + str(count) + " NR==n | awk '{print $2}'", shell=True)

You opened the command parameter with " and there for you need to close it before you do + str() with a " and not a '. Further more i swapped the , 'NR= with + "NR= since you want to append more to your command and not pass a argument to subprocess.call().

As pointed out in the comments, there's no point in splitting the command with shlex since piping commands isn't implemented in subprocess, I would however like to point out that using shell=True is usually not recommended because for instance one of the examples given here.

Community
  • 1
  • 1
Torxed
  • 19,906
  • 13
  • 73
  • 114
  • 2
    you miss a blank between `n=str(count)` and `NR==n` – co2y May 30 '16 at 09:21
  • @J.F.Sebastian Didn't know, thanks for pointing that out. Usually don't pipe things in subprocess. Correcting my answer. – Torxed May 30 '16 at 11:05
  • @J.F.Sebastian Haha, I'm just full of faults today hehe. I was hasty on the gun on that one, had solved a question a minute earlier with metacharacter issues and just bluntly assumed this was such a case again : ) Fixed! Also thanks for mentioning what the down vote is for, it's for this very reason I wish people did it more often so we who answer questions correctly can perfect our knowledge when we too make mistakes. – Torxed May 30 '16 at 11:10
0

An other vay is using format:

pid = subprocess.call("ps -ef | grep app | awk -v n={} NR==n | awk '{{print $2}}'".format(str(count)), shell=True)
Paul
  • 275
  • 1
  • 9
  • don't use `'..n={}..'.format(str(count))`, use `'..n={n}..'.format(n=count)` instead. – jfs May 30 '16 at 11:05
0

Your Awk pipeline could be simplified a great deal - if the goal is to print the last match, ps -ef | awk '/app/ { p=$2 } END { print p }' does that. But many times, running Awk from Python is just silly, and performing the filtering in Python is convenient and easy, as well as obviously more efficient (you save not only the Awk process, but also the pesky shell=True).

for p in subprocess.check_output(['ps', '-ef']).split('\n'):
    if 'app' in p:
        pid = p.split()[1]
tripleee
  • 139,311
  • 24
  • 207
  • 268
  • downvote—`call()` returns the exit status (an integer), not a string. To learn how to read subprocess' output line-by-line, see [this answer](http://stackoverflow.com/a/17698359/4279). Though if we are reimplementing the shell command in Python then we could use `psutil` module. – jfs May 31 '16 at 11:50
  • @J.F.Sebastian Oops, my bad, carelessly copied from the OP's code. Changed to use `check_output()` instead (which however won't work with Pythons older than 2.7). – tripleee May 31 '16 at 11:52
  • @J.F.Sebastian The other answers here seem to use `subprocess.call()` too...? – tripleee May 31 '16 at 11:54
  • `check_output(['ps', '-ef']).split('\n')` won't work in Python 3. Yes, `pid` name as the result of `call()` is misleading. – jfs May 31 '16 at 12:08