gpt4 book ai didi

python - 从 Paramiko 命令捕获标准输出

转载 作者:太空狗 更新时间:2023-10-30 02:29:43 24 4
gpt4 key购买 nike

我对 Paramiko 的 SSHClient.exec_command() 进行了包装。我想捕获标准输出。这是我的函数的简化版本:

def __execute(self, args, sudo=False, capture_stdout=True, plumb_stderr=True,
ignore_returncode=False):

argstr = ' '.join(pipes.quote(arg) for arg in args)

channel = ssh.get_transport().open_session()
channel.exec_command(argstr)

channel.shutdown_write()

# Handle stdout and stderr until the command terminates
captured = []

def do_capture():
while channel.recv_ready():
o = channel.recv(1024)
if capture_stdout:
captured.append(o)
else:
sys.stdout.write(o)
sys.stdout.flush()

while plumb_stderr and channel.recv_stderr_ready():
sys.stderr.write(channel.recv_stderr(1024))
sys.stderr.flush()

while not channel.exit_status_ready():
do_capture()

# We get data after the exit status is available, why?
for i in xrange(100):
do_capture()

rc = channel.recv_exit_status()
if not ignore_returncode and rc != 0:
raise Exception('Got return code %d executing %s' % (rc, args))

if capture_stdout:
return ''.join(captured)

paramiko.SSHClient.execute = __execute

do_capture() 中,每当 channel.recv_ready() 告诉我可以从命令的标准输出接收数据时,我调用 channel.recv(1024 ) 并将数据附加到我的缓冲区。我在命令的退出状态可用时停止。

但是,似乎更多的标准输出数据在退出状态之后的某个时刻出现。

# We get data after the exit status is available, why?
for i in xrange(100):
do_capture()

我不能只调用一次 do_capture(),因为它似乎 channel.recv_ready() 会在几毫秒内返回 False,然后返回 True,并且收到更多数据,然后再次返回 False。

我正在使用 Python 2.7.6 和 Paramiko 1.15.2。

最佳答案

我遇到了同样的问题。问题是命令退出后,stout 或 stderr 缓冲区中可能仍有数据,仍在通过网络或其他任何方式传输。我通读了 paramiko 的源代码,显然一旦 chan.recv() 返回空字符串,所有数据都被读取了。

所以这是我尝试解决它,直到现在它一直有效。

def run_cmd(ssh, cmd, stdin=None, timeout=-1, recv_win_size=1024):
'''
Run command on server, optionally sending data to its stdin

Arguments:
ssh -- An instance of paramiko.SSHClient connected
to the server the commands are to be executed on
cmd -- The command to run on the remote server
stdin -- String to write to command's standard input
timeout -- Timeout for command completion in seconds.
Set to None to make the execution blocking.
recv_win_size -- Size of chunks the output is read in

Returns:
A tuple containing (exit_status, stdout, stderr)
'''

with closing(ssh.get_transport().open_session()) as chan:
chan.settimeout(timeout)
chan.exec_command(cmd)
if stdin:
chan.sendall(stdin)
chan.shutdown_write()

stdout, stderr = [], []

# Until the command exits, read from its stdout and stderr
while not chan.exit_status_ready():
if chan.recv_ready():
stdout.append(chan.recv(recv_win_size))
if chan.recv_stderr_ready():
stderr.append(chan.recv_stderr(recv_win_size))

# Command has finished, read exit status
exit_status = chan.recv_exit_status()

# Ensure we gobble up all remaining data
while True:
try:
sout_recvd = chan.recv(recv_win_size)
if not sout_recvd and not chan.recv_ready():
break
else:
stdout.append(sout_recvd)
except socket.timeout:
continue

while True:
try:
serr_recvd = chan.recv_stderr(recv_win_size)
if not serr_recvd and not chan.recv_stderr_ready():
break
else:
stderr.append(serr_recvd)
except socket.timeout:
continue

stdout = ''.join(stdout)
stderr = ''.join(stderr)

return (exit_status, stdout, stderr)

关于python - 从 Paramiko 命令捕获标准输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31002992/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com