gpt4 book ai didi

执行时间长的 Python Paramiko 超时,需要完整输出

转载 作者:太空狗 更新时间:2023-10-30 01:09:27 27 4
gpt4 key购买 nike

有很多主题涉及标题的一部分,但没有一个能完全满足整个主题。我在远程服务器上推送一个命令,需要在很长的执行时间(比如 5 分钟左右)后获得完整的输出。使用 channel 我能够设置超时,但是当我读回标准输出时我只得到了一小部分输出。解决方案似乎是等待 channel.exit_status_ready()。这适用于成功的调用,但失败的调用永远不会触发 channel 超时。查看文档后,我推测这是因为超时仅适用于读取操作,等待退出状态不符合条件。这是那个尝试:

channel = ssh.get_transport().open_session()
channel.settimeout(timeout)
channel.exec_command(cmd) # return on this is not reliable
while True:
try:
if channel.exit_status_ready():
if channel.recv_ready(): # so use recv instead...
output = channel.recv(1048576)
break
if channel.recv_stderr_ready(): # then check error
error = channel.recv_stderr(1048576)
break
except socket.timeout:
print("SSH channel timeout exceeded.")
break
except Exception:
traceback.print_exc()
break

很漂亮,不是吗?希望它有效。

我第一次尝试解决方案是使用 time.time() 开始,然后检查开始 - time.time() > 超时。这看起来很简单,但在我目前的版本中,我输出了 start - time.time() 和一个应该触发中断的固定超时......并且看到了双倍和三倍超时的差异而没有发生中断。为节省篇幅,我将提及我的第三次尝试,我已将其与本次一起汇总。我在这里阅读了有关使用 select.select 等待输出的信息,并在文档中指出那里也有超时。正如您将从下面的代码中看到的,我混合了所有三种方法—— channel 超时、time.time 超时和选择超时——但仍然必须终止进程。这是弗兰肯代码:

channel = ssh.get_transport().open_session()
channel.settimeout(timeout)
channel.exec_command(cmd) # return on this is not reliable
print("{0}".format(cmd))
start = time.time()
while True:
try:
rlist, wlist, elist = select([channel], [], [],
float(timeout))
print("{0}, {1}, {2}".format(rlist, wlist, elist))
if rlist is not None and len(rlist) > 0:
if channel.exit_status_ready():
if channel.recv_ready(): # so use recv instead...
output = channel.recv(1048576)
break
elif elist is not None and len(elist) > 0:
if channel.recv_stderr_ready(): # then check error
error = channel.recv_stderr(1048576)
break
print("{0} - {1} = {2}".format(
time.time(), start, time.time() - start))
if time.time() - start > timeout:
break
except socket.timeout:
print("SSH channel timeout exceeded.")
break
except Exception:
traceback.print_exc()
break

这是一些典型的输出:

[<paramiko.Channel 3 (open) window=515488 -> <paramiko.Transport at 0x888414cL (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>], [], []
1352494558.42 - 1352494554.69 = 3.73274183273

顶行是 [rlist, wlist, elist] from select,底行是 time.time() - start = (time.time() - start)。我通过计算迭代次数并在循环 1000 次后在尝试底部中断来中断运行。示例运行中的超时设置为 3。这证明我们通过了尝试,但显然,三种应该超时的方法都不起作用。

如果我从根本上误解了某些内容,请随意修改代码。我希望它成为 uber-Pythonic 并且仍在学习中。

最佳答案

虽然我仍在测试中,但这里有一些可能有用的东西。在与各种类型的超时(包括 Python 的 catch-all 超时)作斗争并意识到真正的问题是不能信任服务器终止进程之后,我这样做了:

chan = ssh.get_transport().open_session()

cmd = "timeout {0} {1}\n".format(timeouttime, cmd)

chan.exec_command(cmd)

如果 cmd 没有尽早退出,服务器将在 timeouttime 后超时,正如我所希望的那样,终止的命令会终止 channel 。唯一的问题是 GNU coreutils 必须存在于服务器上。如果没有其他选择。

关于执行时间长的 Python Paramiko 超时,需要完整输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13316134/

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