【发布时间】:2020-04-04 00:49:33
【问题描述】:
为方便起见,我编写了一个小包装类来登录远程主机,执行命令,结束检索数据:
def MySSHClient:
def connect(self, remoteHost, remotePort, userName, password):
self.__s = paramiko.SSHClient()
self.__s.load_system_host_keys()
self.__s.connect(remoteHost, remotePort, userName, password)
def exec_command(self, command):
bufsize = -1
chan = self.__s.get_transport().open_session()
chan.exec_command(command)
stdin = chan.makefile('wb', bufsize)
stdout = chan.makefile('r', bufsize)
stderr = chan.makefile_stderr('r', bufsize)
stdin.close()
exitcode = chan.recv_exit_status()
r = MySSHCommandResult(command, stdin, stdout, stderr, exitcode)
chan.close()
return r
def close(self):
self.__s.close()
此代码改编自原始 paramiko python 实现。我刚刚添加了最后 5 行。
(仅供参考:MySSHCommandResult 在构建期间从 stdout 和 strerr 读取所有数据并将其存储以供进一步使用。)
MySSHClient 类在一个简单的 python 程序中使用:
....
exitCode = 0
s = None
try:
....
exitCode = 3
s = MySSHClient()
s.connect(host, port, login, password)
exitCode = 4
result = s.exec_command(myCommand)
exitCode = 5
if not result.isSuccess():
raise Exception("Failed to execute command!")
result.dump() # for current debugging purposes
exitCode = 0
except:
pass
if s is not None:
s.close()
sys.exit(exitCode)
(通过这些退出代码,python 程序会告诉调用者一切是否成功。如您所见,使用了各种退出代码以便在失败时进行一些错误诊断。)
到目前为止一切顺利。基本上这行得通。但我不明白的是,有时我的 python 程序会提供这样的额外输出:
Exception ignored in: <bound method BufferedFile.__del__ of <paramiko.ChannelFile from <paramiko.Channel 0 (closed) -> <paramiko.Transport at 0x74300588 (unconnected)>>>>
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/paramiko/file.py", line 61, in __del__
File "/usr/local/lib/python3.5/dist-packages/paramiko/file.py", line 79, in close
File "/usr/local/lib/python3.5/dist-packages/paramiko/file.py", line 88, in flush
TypeError: 'NoneType' object is not callable
或者像这样:
Exception ignored in: <object repr() failed>
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/paramiko/file.py", line 61, in __del__
File "/usr/local/lib/python3.5/dist-packages/paramiko/file.py", line 79, in close
File "/usr/local/lib/python3.5/dist-packages/paramiko/file.py", line 88, in flush
TypeError: 'NoneType' object is not callable
一切正常,但有大约 10% 到 20% 的时间我会看到这些错误消息。有谁知道为什么有时程序终止时清理会失败?如何避免这些错误消息?
【问题讨论】:
-
您使用的是哪个版本的 paramiko,确切地说?
-
感谢您的提问!我正在这里安装一个全新的 Ubuntu 16.04。奇怪的是安装了 paramiko 1.17.0。尽管如此,升级到最新版本的 paramiko - 2.0.0 版 - 并没有改变任何东西。甚至错误消息的行号也保持不变。我刚刚通过 pip3 升级,用 2.0.0 版本测试,没有用。
-
这很可能是 paramiko 错误。你应该写一个错误报告。此外,您应该确保
chan.makefile()打开的每个“文件”都是close()d。尽管仅此一项不太可能解决问题,但它可以确保在出现此错误时不会丢失任何数据。 -
嗯。你真的认为这是一个错误?考虑到可能有数百万人在使用 paramiko,我不这么认为。
-
查看
paramiko/file.py的第88行,唯一被调用的对象是BytesIO。这可以“突然”变成None的唯一方法是在解释器关闭时进行垃圾收集(除非有人在某处明确设置它None,这是不太可能的)。