子进程无法运行通过终端可正常运行的命令生成的命令

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

fileformat和filteruser也可以为空

以下是配置文件

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

这是我想在 subprocess 上运行的命令。使用 pdb 检查上述变量值,显示如下值且看起来很棒。
['sudo', 'cat', '/etc/haproxy/haproxy.global.inc', '|', 'egrep', '-v', "''"]

在终端手动运行 sudo cat /etc/haproxy/haproxy.global.inc | egrep -v " '' " 的代码非常好用。

为什么子进程不能处理它呢?

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


尝试使用以下命令['sudo', 'cat', '/etc/haproxy/haproxy.global.inc'],观察是否可行。 - alpheus
我需要一个过滤器,例如可能有可用的 egrep,所以我正在使用它,但是感谢您帮助我找出问题在那之后。 - Tara Prasad Gurung
我只是想找出问题的根源,只需检查并查看是否仅猫命令有效,然后我们可以从那里开始。 - alpheus
是的,问题就在过滤器中。 - Tara Prasad Gurung
1
尝试运行以下命令:subprocess.call(["sudo cat /etc/haproxy/haproxy.global.inc | egrep -v ''"], shell=True) - alpheus
显示剩余2条评论
3个回答

3

您的shell将接受一个命令,如$ a | b | c,并将其转换为三个独立的进程(a、b、c),并将一个进程的输出附加到链中下一个进程的输入。

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

上面的命令将执行sudo命令(这将转而分叉cat命令,并将所有剩余的参数传递给cat)。它不理解"|"符号。它只是将其视为另一个参数。是cat在抱怨它不能打开"|","egrep"等,并将这些当作文件名传递给cat。

您可以尝试使用shell=True的Popen。我没有尝试过这个方法,也不确定它是否会处理管道。

另一个选项是使用Popen仅执行sudo命令(无过滤器),然后使用Popen.communicate从python读取命令的输出,并在python中进行空行过滤。

编辑: 我快速检查了一下shell=True。以下是脚本:

#!/usr/bin/env python
import subprocess

subprocess.call(["ls", "-l", "|", "cat"], shell=False)
  • 如果使用shell=False,会出现以下错误:ls: cat: No such file or directoryls: |: No such file or directory。这是正常的,因为ls试图列出|cat的内容。
  • 如果使用shell=True,可以得到期望的输出。也就是说,ls的输出被管道传输到cat中。终端正在处理|

shell=True 真的不会有什么帮助。 - Tara Prasad Gurung
为什么不呢?你正在尝试使用 shell 管道,这应该可以使它工作。 - cha0site
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 这是我传递了shell=True的方式,但如前所述,无法工作。从Python筛选可能会起作用,但那样会增加额外的负担,并且无法满足我的需求。我想要使用egrep进行过滤而不是解析。 - Tara Prasad Gurung
命令 = ["ssh", "{user}@{host}".format(user=user, host=host), "sudo", "cat", "/etc/passwd", "|", "egrep", "-v", ""{filters}"".format(filters=filteruser)]。这是我的另一个模块,我也做了过滤,但只提供了文件路径。为什么动态提供路径不起作用?两个步骤可能会解决问题,但为什么在单个进程中也有过滤器的情况下可以工作呢? - Tara Prasad Gurung

0

你可以使用已经建议的 shell=True,或者使用 subprocess 进行管道操作:

p1 = subprocess.Popen(['sudo', 'cat', '/etc/haproxy/haproxy.global.inc'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['egrep', '-v', "''"], stdin=p1.stdout,stdout=subprocess.PIPE)

命令 = ["ssh", "{user}@{host}".format(user=user, host=host), "sudo", "cat", "/etc/passwd", "|", "egrep", "-v", ""{filters}"".format(filters=filteruser)]这是我的另一个模块,我已经进行了过滤,但只提供了文件路径。为什么动态提供路径不起作用呢?可能需要2个步骤来解决,但为什么这种方法起作用而另一种方法不起作用呢? - Tara Prasad Gurung

0

命令和过滤器如上

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

子进程

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

output, err = filtration.communicate()

是的,我使用了一个两步解决方案,无法找到单一最佳参考,Python subprocess command with pipe


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接