0

I am trying to automate the process of executing a command. When I this command:

ps -eo pcpu,pid,user,args | sort -k 1 -r | head -10

Into a termianl I get the response:

%CPU   PID USER     COMMAND
 5.7 25378 stackusr whttp
 4.8 25656 stackusr tcpproxy

But when I execute this section of code I get an error regarding the format specifier:

  if __name__ == '__main__':
        fullcmd = ['ps','-eo','pcpu,pid,user,args | sort -k 1 -r | head -10']
        print fullcmd
        sshcmd = subprocess.Popen(fullcmd,
                    shell= False,
                    stdout= subprocess.PIPE,
                    stderr= subprocess.STDOUT)
        out = sshcmd.communicate()[0].split('\n')
        #print 'here'
        for lin in out:
            print lin

This is the error showen:

ERROR: Unknown user-defined format specifier "|".
********* simple selection *********  ********* selection by list *********
-A all processes                      -C by command name
-N negate selection                   -G by real group ID (supports names)
-a all w/ tty except session leaders  -U by real user ID (supports names)
-d all except session leaders         -g by session OR by effective group name
-e all processes                      -p by process ID
T  all processes on this terminal     -s processes in the sessions given
a  all w/ tty, including other users  -t by tty
g  OBSOLETE -- DO NOT USE             -u by effective user ID (supports names)
r  only running processes             U  processes for specified users
x  processes w/o controlling ttys     t  by tty

I have tryed placing a \ before the | but this has not effect.

Barmar
  • 741,623
  • 53
  • 500
  • 612
Bawn
  • 509
  • 3
  • 13
  • 36
  • 1
    Isn't the answer in [the documentation](https://docs.python.org/2/library/subprocess.html#replacing-shell-pipeline)? – bufh Jul 29 '15 at 20:34
  • related: [How do I use subprocess.Popen to connect multiple processes by pipes?](http://stackoverflow.com/q/295459) – jfs Jul 30 '15 at 17:30
  • 1
    you could use [`psutil` module](https://pypi.python.org/pypi/psutil) instead of running the `ps` external process. – jfs Jul 30 '15 at 17:31

1 Answers1

3

You would need to use shell=True to use the pipe character, if you are going to go down that route then using check_output would be the simplest approach to get the output:

from subprocess import check_output

out = check_output("ps -eo pcpu,pid,user,args | sort -k 1 -r | head -10",shell=True,stderr=STDOUT)

You can also simulate a pipe with Popen and shell=False, something like:

from subprocess import Popen, PIPE, STDOUT
sshcmd = Popen(['ps', '-eo', "pcpu,pid,user,args"],
               stdout=PIPE,
               stderr=STDOUT)
p2 = Popen(["sort", "-k", "1", "-r"], stdin=sshcmd.stdout, stdout=PIPE)
sshcmd.stdout.close()
p3 = Popen(["head", "-10"], stdin=p2.stdout, stdout=PIPE,stderr=STDOUT)
p2.stdout.close()
out, err = p3.communicate()
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • `stderr=STDOUT` does not correspond to the shell command. It might be simpler to start `head` process first with `stdin=PIPE` and pass this pipe to `sort` process stdout (`stdout=head.stdin`). It avoids `.close()` calls. See [this answer](http://stackoverflow.com/a/9164238/4279) – jfs Jul 30 '15 at 17:35