6
cmd= ["sudo", "cat", "{filepath}".format(filepath=filepath), "|","egrep", "-v","\'{filteruser}\'".format(filteruser=filteruser)]

fileformat and filteruser can be blank too

config file below

[plugin_haproxy]
user= tara
host=localhost
filepath=/etc/haproxy/haproxy.global.inc
filter=

This is the command I want to run on subprocess, checking the above variable values with pdb shows bellow value and looks great

['sudo', 'cat', '/etc/haproxy/haproxy.global.inc', '|', 'egrep', '-v', "''"]

Manullay running the code sudo cat /etc/haproxy/haproxy.global.inc | egrep -v " '' " on terminal works great

Why is subprocess not able to process it.

"cat: |: No such file or directory\ncat: egrep: No such file or directory\ncat:

Tara Prasad Gurung
  • 3,422
  • 6
  • 38
  • 76

3 Answers3

3

your shell will take a command such $ a | b | c and turn it into three separate processes (a,b,c) and attach the output of one to the input of the next in the chain.

['sudo', 'cat', '/etc/haproxy/haproxy.global.inc', '|', 'egrep', '-v', "''"]

The above will execute the sudo command (which will in-turn fork the cat command and pass all the remaining args to cat). It doesn't understand the "|" symbol. It just treats it as another arg. It is cat that is complaining that it can not open "|", "egrep", etc at it is treating these as file names to cat.

You can try the Popen with shell=True. I have not tried that and not sure if it will handle pipes.

The other option is to use Popen to execute the sudo command only (no filter) and then use Popen.communicate to read the output from the command in python and do the empty line filtering in python.

EDIT: I did a quick check for the shell=True. Here is the script below:

#!/usr/bin/env python
import subprocess

subprocess.call(["ls", "-l", "|", "cat"], shell=False)
  • With shell=False, I get the following error: ls: cat: No such file or directory and ls: |: No such file or directory. This is expected as ls is trying to list the contents of | and cat.
  • with shell=True, I get the desired output. That is, the output of ls is piped to cat. The shell is processing the |.
  • shell=True is really not going to help – Tara Prasad Gurung Mar 29 '17 at 07:01
  • Why not? You're trying to use shell pipes, this should make it work. – cha0site Mar 29 '17 at 08:49
  • `p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)` This is how I have passed shell=True and as mentioned before not working. filtering from python might work but that dont want extra burden and wont fulfill my need i want the filter with egrep not by parsing – Tara Prasad Gurung Mar 29 '17 at 09:05
  • `command = ["ssh", "{user}@{host}".format(user=user, host=host), "sudo", "cat", "/etc/passwd", "|", "egrep", "-v", "\"{filters}\"".format(filters=filteruser)]` This is another module of mine where I have done the filtering too but only the file path is directly provided. Why providing the path too dynamically not working. 2 steps might solve but why is this working than where I have a filter too in single process – Tara Prasad Gurung Mar 29 '17 at 09:15
0

You can either use shell=True as was already suggested, or use subprocess to pipe:

p1 = subprocess.Popen(['sudo', 'cat', '/etc/haproxy/haproxy.global.inc'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['egrep', '-v', "''"], stdin=p1.stdout,stdout=subprocess.PIPE)
cha0site
  • 10,517
  • 3
  • 33
  • 51
  • `command = ["ssh", "{user}@{host}".format(user=user, host=host), "sudo", "cat", "/etc/passwd", "|", "egrep", "-v", "\"{filters}\"".format(filters=filteruser)]` This is another module of mine where I have done the filtering too but only the file path is directly provided. Why providing the path too dynamically not working. 2 steps might solve but why is this working than . – Tara Prasad Gurung Mar 29 '17 at 09:13
0

Command and filter above

command = ["sudo", "cat", "{filepath}".format(filepath=filepath)]         
userfilter = ["egrep", "-v", "\"{filteruser}\"".format(filteruser=filteruser)***]

Subprocess

cmdout = subprocess.Popen(command, stdout=subprocess.PIPE)
filtration = subprocess.Popen(runfilter, stdin=cmdout.stdout,stdout=subprocess.PIPE)

output, err = filtration.communicate()

Yes,I used a two steps solutions could not find a single best refer here,Python subprocess command with pipe

Community
  • 1
  • 1
Tara Prasad Gurung
  • 3,422
  • 6
  • 38
  • 76