在python中运行它时捕获shell脚本的LIVE输出

时间:2015-01-29 12:10:19

标签: python shell subprocess

我正在编写一个python脚本来ssh到linux服务器并执行已经存储在linux服务器上的shell脚本。

这是我的代码到目前为止的样子

command = ['ssh into the remote server',
           'cd into the directory of the shell script,
           './running the shell script',
           ]

process = subprocess.Popen(command,
                            shell=True,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)

err, out = process.communicate()

if out: 
    print "standard output of subprocess is : "
    print out
if err:
    print "standard error of subprocess is : "
    print err
print "returncode of subprocess: "
print process.returncode

第一个问题:我可以通过stderr获取shell脚本的输出,但是我只在整个shell脚本执行完毕后才获得它。因此,如果shell脚本需要10分钟才能完成,我只能在10分钟后看到shell脚本的输出。 我希望我的shell脚本的输出逐行返回给我,就像我在远程服务器中手动执行脚本一样。可以这样做吗?

第二个问题:正如你所看到的,我的命令列表中有三个命令(这只是我所有命令的一小部分),如果我将所有命令放在列表中,我只获取所有命令的输出只有当我的所有命令都完成执行时才通过stdout执行命令。如果我的第一个问题无法完成,是否有办法在每个命令执行完毕后至少获取每个命令的输出,而不是仅在所有命令都已执行完毕后立即接收所有命令。

3 个答案:

答案 0 :(得分:0)

我不完全确定,但如果您将其他两个命令作为参数传递给ssh,也许您可​​以获得即时输出:

command = 'ssh user@example.com \'cd some/path/on/your/server; ./run-the-script.sh\''

我理解它的方式,Python首先读取并处理所有输入,只有然后返回输出。我对Python不太熟悉,所以我可能错了,但如果我说对了,这应该会有所帮助。

答案 1 :(得分:0)

请勿致电.communicate() - 等待流程完成。

相反,请继续从.stdout管道中读取数据。

简单示例:

In [1]: import subprocess
In [2]: p = subprocess.Popen(["find", "/"], stdout=subprocess.PIPE)


In [3]: p.stdout
Out[3]: <open file '<fdopen>', mode 'rb' at 0x7f590446dc00>

In [4]: p.stdout.readline()
Out[4]: '/\n'

In [5]: p.stdout.readline()
Out[5]: '/var\n'

In [6]: p.stdout.readline()
Out[6]: '/var/games\n'

答案 2 :(得分:0)

要立即查看输出,请勿重定向:

from subprocess import Popen, PIPE

p = Popen(['ssh', 'user@hostname'], stdin=PIPE) 
p.communicate(b"""cd ..
echo 1st command
echo 2nd command
echo ...
""")

如果您希望两者捕获变量中的“实时”输出以在终端中显示它,那么解决方案取决于您是否需要处理stdin / stdout / stderr同时发生。

如果输入很小并且您想要组合stdout / stderr,那么您可以立即传递所有命令并逐行读取合并的输出:

from subprocess import Popen, PIPE, STDOUT

p = Popen(['ssh', 'user@hostname'], stdin=PIPE,
          stdout=PIPE, stderr=STDOUT, bufsize=1) 
p.stdin.write(b"""cd ..
echo 1st command
echo 2nd command
echo ...
""")
p.stdin.close() # no more input

lines = [] # store output here
for line in iter(p.stdout.readline, b''): # newline=b'\n'
    lines.append(line) # capture for later
    print line, # display now
p.stdout.close()
p.wait()

如果您想分别捕获“live”stdout / stderr,请参阅: