paramiko批量执行脚本sdtout.read() hung的问题
-
问题描述
python做批量自动化操作的时候,很多人都会用paramiko模块,最近遇到有些命令执行的时候会卡住不退出,导致脚本跑不下去的问题,困扰了许久。 -
解决
通过Stack Overflow查找,其实人家老外早已遇到过这个问题,如下。
it is due to stdout.channel.eof_received == 0.
import paramiko
>>> client = paramiko.SSHClient()
>>> client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
>>> client.connect("1.1.1.1", username="root", password="pass")
>>> stdin, stdout, stderr = client.exec_command("service XXX start")
stdin, stdout and stderr are staying open…
>>> print stdin
<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 in-buffer=50 -> <paramiko.Transport at 0x17eff90L (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>
>>> print stdout
<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 in-buffer=50 -> <paramiko.Transport at 0x17eff90L (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>
>>> print stderr
<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 in-buffer=50 -> <paramiko.Transport at 0x17eff90L (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>
So EOF was not received…
>>> print stdin.channel.eof_received
0
Usually I receive True and can just stdout.read(), but to be safe i use this workaround (which works!):
Wait for a timeout, force stdout.channel.close() and then stdout.read():
>>> timeout = 30
>>> import time
>>> endtime = time.time() + timeout
>>> while not stdout.channel.eof_received:
... sleep(1)
... if time.time() > endtime:
... stdout.channel.close()
... break
>>> stdout.read()
'Starting XXX: \n[ OK ]\rProgram started . . .\n'
>>>
意思就是说,如果会话一直不能read,设置一个超时时间,超过超时时间,自动结束这个session。
实际尝试下来,效果就是,如果你运行的程序,或者脚本,运行时间过长,python会帮你结束ssh,把命令留在后台执行。
但是这样有一个问题,因为留在后台执行,原本不能执行的命令确实是可以执行了,但是看不出命令是否执行完毕了。
解决了一个老问题,又出一个新问题。