Paramiko通道在读取大输出时卡住
我有一段代码,它可以在远程的Linux机器上执行命令,并使用Paramiko读取输出。代码大概是这样的:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(IPAddress, username=user['username'], password=user['password'])
chan = self.ssh.get_transport().open_session()
chan.settimeout(10800)
try:
# Execute thecommand
chan.exec_command(cmd)
contents = StringIO.StringIO()
data = chan.recv(1024)
# Capturing data from chan buffer.
while data:
contents.write(data)
data = chan.recv(1024)
except socket.timeout:
raise socket.timeout
output = contents.getvalue()
return output,chan.recv_stderr(600),chan.recv_exit_status()
这段代码在处理小的输出时运行得很好,但当输出变大时,它就会卡住。
这里面是不是有什么和缓冲区有关的问题呢?
6 个回答
2
其实我觉得上面所有的回答都没能解决真正的问题:
如果远程程序首先产生大量的错误输出(stderr),那么
stdout.readlines()
stderr.readlines()
就会一直卡在那里。虽然
stderr.readlines()
stdout.readlines()
可以解决这种情况,但如果远程程序首先产生大量的正常输出(stdout),那就会失败。
我还没有找到解决办法……
9
我在这里分享最终的代码,这段代码是根据布鲁斯·韦恩(:))的输入写的。
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(IPAddress, username=user['username'], password=user['password'])
chan = self.ssh.get_transport().open_session()
chan.settimeout(10800)
try:
# Execute the given command
chan.exec_command(cmd)
# To capture Data. Need to read the entire buffer to capture output
contents = StringIO.StringIO()
error = StringIO.StringIO()
while not chan.exit_status_ready():
if chan.recv_ready():
data = chan.recv(1024)
#print "Indside stdout"
while data:
contents.write(data)
data = chan.recv(1024)
if chan.recv_stderr_ready():
error_buff = chan.recv_stderr(1024)
while error_buff:
error.write(error_buff)
error_buff = chan.recv_stderr(1024)
exit_status = chan.recv_exit_status()
except socket.timeout:
raise socket.timeout
output = contents.getvalue()
error_value = error.getvalue()
return output, error_value, exit_status
3
我没有看到和标准输出(stdout)相关的问题,但我不太确定你处理标准错误(stderr)的方式。你能确认一下,是不是捕获标准错误导致了问题吗?我会试试你的代码,然后告诉你结果。
更新:当你执行的命令在标准错误中输出很多信息时,你的代码会卡住。我不太明白为什么,但可能是recv_stderr(600)
引起的。所以,捕获错误信息的方式要和捕获标准输出的方式一样。
contents_err = StringIO.StringIO()
data_err = chan.recv_stderr(1024)
while data_err:
contents_err.write(data_err)
data_err = chan.recv_stderr(1024)
你可以先试着把recv_stderr(600)
改成recv_stderr(1024)
或者更大的值。