Python 配置SSH远程主机执行命令的超时判断

文章讲述了如何在Python中使用paramiko库进行SSH连接时,处理exec_command命令超时的问题,以及recv_exit_status操作对后续readlines的影响,强调了在处理这类问题时需要正确管理异常和通道状态。
摘要由CSDN通过智能技术生成

干活时发现一个问题,通过以下方式建立一个SSH客户端后:

self.ssh = paramiko.SSHClient()

当我们利用这个SSH去执行命令时:

stdout = self.ssh.exec_command(cmd, timeout, get_pty=True)[1]

此处的cmd指的是要在SSH连上的远程主机操作的命令;

此处的timeout指的是底层 SSH 操作的超时设置,因此不能直接用来对cmd进行一个执行时间的限制。但查资料后发现,有一种办法可以解决这个问题:

stdout = self.ssh.exec_command(cmd, timeout, get_pty=True)[1]
result = stdout.readlines()

在获取stdout后,马上执行一个readlines操作。

这个readlines会去读取stdout来制作列表,如果exec_command在timeout时间内未完成cmd的执行,此时的stdout会是错乱的,因此对stdout进行readlines会直接抛出异常!此时只需要对异常进行相应处理就可以完成想要的效果。 相反,如果是cmd在timeout内执行完成的话,readlines就不会有异常抛出~

举例:

stdout = self.ssh.exec_command(cmd, timeout, get_pty=True)[1]
try:
    result = stdout.readlines()
    self.logger.info(result)
except Exception as e:
    self.logger.error(f'Timeout while executing command: {e}')
    return errno.ETIME    

事实证明,任何对stdout做处理的方式都可以在超时后触发异常:

stdout = self.ssh.exec_command(cmd, timeout, get_pty=True)[1]
try:
    output = stdout.read().decode('utf-8')
    self.logger.info(output)
except Exception as e:
    self.logger.error(f'Timeout while executing command: {e}')
    return errno.ETIME

=========================================================================

原本问题到这里就结束了,但是在调整代码时又发现了一个问题:

如果我执行代码如下:

stdout = self.ssh.exec_command(cmd, timeout, get_pty=True)[1]
exit_stat = stdout.channel.recv_exit_status()
result = stdout.readlines()

在readlines之前添加一行recv_exit_status,就会导致不管exec_command时有没有timeout都不会报错。查资料后发现,当执行recv_exit_status时,不管exec_command的执行状态如何,都会关闭ssh channel通道,即使远程命令尚未执行完毕关闭,且exit_stat都为0(非异常状态)。因此即使远程命令尚未执行完毕,也不会导致readlines()报错,因为通道已经关闭了。这样我们原本建立的 "exec_command->马上抓取stdout状态" 的方式就失效了~  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值