使用子进程运行多个 bash 命令

Posted

技术标签:

【中文标题】使用子进程运行多个 bash 命令【英文标题】:running multiple bash commands with subprocess 【发布时间】:2013-07-18 13:03:52 【问题描述】:

如果我在 bash 中运行 echo a; echo b,结果将是两个命令都运行。但是,如果我使用 subprocess 则运行第一个命令,打印出整个行的其余部分。 下面的代码回显a; echo b 而不是a b,如何让它运行这两个命令?

import subprocess, shlex
def subprocess_cmd(command):
    process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
    proc_stdout = process.communicate()[0].strip() 
    print proc_stdout

subprocess_cmd("echo a; echo b")

【问题讨论】:

相关:这里是how to run multiple shell commands (and optionally capture their output) concurrently 【参考方案1】:

你必须在子进程中使用 shell=True 并且没有 shlex.split:

import subprocess

command = "echo a; echo b"

ret = subprocess.run(command, capture_output=True, shell=True)

# before Python 3.7:
# ret = subprocess.run(command, stdout=subprocess.PIPE, shell=True)

print(ret.stdout.decode())

返回:

a
b

【讨论】:

啊,我明白了,我测试了shell=True,但 command.split() 破坏了它(列表)。另外要提醒其他阅读者,使用shell=True 是一种安全隐患,请确保您信任输入。 您不能将command.split()shell=True 一起使用。实际上subprocess.Popenshell=True 的参数必须是字符串而不是列表。 我发现这有点简单,并且没有输出的乱码: def do_shell(self, command): self.proc=subprocess.Popen(command,shell=True) self .proc.wait() @Ravichandra:注意:标题中的bash。在 Windows 上,您可能需要 echo a & echo b 命令。 您的结果运行/bin/sh,而不是/bin/bash。将 executable='/bin/bash' 添加到 Popen() 参数以获得 bash shell。【参考方案2】:
import subprocess
cmd = "vsish -e ls /vmkModules/lsom/disks/  | cut -d '/' -f 1  | while read diskID  ; do echo $diskID; vsish -e cat /vmkModules/lsom/disks/$diskID/virstoStats | grep -iE 'Delete pending |trims currently queued' ;  echo '====================' ;done ;"


def subprocess_cmd(command):
    process = subprocess.Popen(command,stdout=subprocess.PIPE, shell=True)
    proc_stdout = process.communicate()[0].strip()
    for line in proc_stdout.decode().split('\n'):
        print (line)

subprocess_cmd(cmd)

【讨论】:

欢迎来到 ***!请说明您提供的代码如何回答原始问题。 用管道(|)运行推荐【参考方案3】:

如果您只是一次性运行命令,那么您可以使用subprocess.check_output 便利功能:

def subprocess_cmd(command):
    output = subprocess.check_output(command, shell=True)
    print output

【讨论】:

【参考方案4】:

用“&&”连接命令。

os.system('echo a > outputa.txt && echo b > outputb.txt')

【讨论】:

如果第一个命令有错误,第二个命令将不会运行。我会说使用 ;而是。 这里重要的部分是使用os.system()而不是subprocess os.system 不能替代子进程。 os.system 不能做 subprocess 做的所有事情。 也许不行,但可以echo就好了。【参考方案5】:

我偶然发现了一种情况,我需要在 python 中运行一堆 bash 代码(不使用分号分隔)。在这种情况下,建议的解决方案没有帮助。一种方法是保存一个文件,然后使用Popen 运行它,但在我的情况下这是不可能的。

我最终做的是这样的:

commands = '''
echo "a"
echo "b"
echo "c"
echo "d"
'''

process = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, err = process.communicate(commands)
print out

所以我首先创建子 bash 进程,然后告诉它要执行什么。这种方法消除了将命令直接传递给Popen 构造函数的限制。

【讨论】:

subprocess.check_output(commands, shell=True) 工作得很好。如果命令中有 bash-isms,则传递 executable='/bin/bash' 对于 Python 3,您可能希望使用:out, err = process.communicate(commands.encode('utf-8'))print(out.decode('utf-8')) 如果命令以; 分隔,您可能还需要将shell=True 添加到subprocess.Popen() 行。【参考方案6】:
>>> command = "echo a; echo b"
>>> shlex.split(command);
    ['echo', 'a; echo', 'b']

所以,问题是 shlex 模块不处理“;”

【讨论】:

command.split() 给出['echo', 'a;', 'echo', 'b'] 并且也失败了。 ` @bougui 是对的。设置“shell=True”,Popen 的第一个参数需要一个命令字符串,如“echo a;echo b”。如果没有 "shell=True",Popen 的第一个参数应该是一个列表,例如:["echo","a"]

以上是关于使用子进程运行多个 bash 命令的主要内容,如果未能解决你的问题,请参考以下文章

Python 子进程 - 通过 SSH 运行多个 shell 命令

Python:子进程并运行具有多个参数的 bash 脚本

Python:子进程并运行带有多个参数的bash脚本

使用子进程从 Python 运行 PDAL bash 命令的问题 [重复]

实时打印使用 Python 中的子进程启动的 bash 命令的结果

linux进入子进程的命令是