paramiko执行较长时间出现卡住的情况记录

本文探讨了使用Paramiko库远程执行命令时遇到的问题,即命令执行完毕后,Paramiko仍处于等待状态。通过调整服务器端配置解决了SSH会话过期问题。

当在服务器上执行压测的时候,会遇到进程后台已经执行完了,但是paramiko这边卡住的情况。看了文档及参考了codenong里面的代码,debug之后发现channel中的exit_status_ready,recv_ready, recv_stderr_ready始终是false的,并没有找到解决的办法。在github的paramiko目录下看到有类似的提问,没有解答。

while not stdout.channel.exit_status_ready():
	time.sleep(10)
	if stdout.channel.recv_ready():
	    och = stdout.channel.recv(1024)
	    while och:
	        stdoutResult += och.decode()
	        och = stdout.channel.recv(1024)
	if stdout.channel.recv_stderr_ready():
	    ech = stdout.channel.recv_stderr(1024)
	    while ech:
	        stderrResult += och.decode()
	        ech = stdout.channel.recv_stderr(1024)

https://github.com/paramiko/paramiko/issues/1507
上面这里有提到一个方法,但没看懂要做的方式。目前的实现方式为命令后台执行
nohup command &
执行完会自动退出, 然后判断进程是否存在, 存在就sleep, 直到多少次后进程执行完毕, 然后根据日志最后的内容来判断是否正常执行完成。

------------------------------2022-09-23新增---------------------------------------------------------------------------
服务器这边需要设置两个参数,排查出来主要的原因是ssh会话过期导致的。paramiko这边其实是没有问题的,尝试增加了paramiko这边的set_keepalive, 但不是必要的。 服务器参数是必须的。需要修改的参数补充如下。

 1、修改/etc/ssh/sshd_config配置文件中以下两个参数:
1)、ClientAliveInterval:设置为想要的时间,单位为秒,比如设置为60秒,则服务器每1分钟向客户端发送保持连接的请求。
2)、ClientAliveCountMax:此参数指服务器根据ClientAliveInterval时间间隔发送保持连接的请求时,如果发现客户端没有响应,则判断为一次超时,这个参数设置允许超时的次数。默认为3,客户端一般不会没响应,设置为默认值3即可。
假如ClientAliveInterval为60,ClientAliveCountMax为3,则实际的超时时间为60*3=3分钟。
修改之后需要重启sshd服务 systemctl restart sshd

参考:

https://docs.paramiko.org/en/2.6/api/transport.html#paramiko.transport.Transport.set_keepalive
https://www.codenong.com/14643861/
https://www.cnblogs.com/caesar-id/p/12873557.html
https://docs.paramiko.org/en/stable/api/channel.html
https://blog.youkuaiyun.com/donghustone/article/details/83054138

`paramiko`是一个Python库,用于通过SSH协议远程执行Linux或Unix系统的命令。如果你在执行耗时较长的命令时想要不影响后续命令的执行,可以考虑以下几个策略: 1. **异步执行**:使用`paramiko`的`Transport`和`Channel`类进行非阻塞I/O操作。你可以创建一个单独的线程或进程来运行长时间的命令,并将结果存储在一个队列或者其他数据结构中,待该命令完成后再继续处理。 ```python import paramiko from queue import Queue def run_command(command, result_queue): ssh = paramiko.SSHClient() # ...其他连接配置... try: stdin, stdout, stderr = ssh.exec_command(command) for line in iter(stdout.readline, b''): result_queue.put(line.decode()) # ...处理结果... finally: ssh.close() # 创建一个结果队列 result_queue = Queue() command = "your_long_running_command" thread = threading.Thread(target=run_command, args=(command, result_queue)) thread.start() # 主线程继续执行其他命令 while thread.is_alive(): if not result_queue.empty(): print(result_queue.get()) # 等待主线程完成 ``` 2. **分段执行**:如果命令可以拆分成几个部分,可以依次执行每个部分,然后等待前一部分执行完再进行下一部分。 3. **信号处理**:在Linux系统中,可以尝试使用`subprocess`模块并设置`preexec_fn=os.setpgrp()`来创建一个新的进程组,这使得子进程不会影响到父进程的时间限制。 ```python import subprocess import signal def handler(signum, frame): raise KeyboardInterrupt with open('output.txt', 'w') as f: p = subprocess.Popen(['long_running_command'], stdout=subprocess.PIPE, preexec_fn=os.setpgrp) while True: output = p.stdout.read(1) # 非阻塞读取 if not output: break f.write(output.decode()) # 写入结果 signal.pause() # 挂起进程直到收到中断信号(如Ctrl+C) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值