Paramiko:使用'select'异步读取长Shell脚本输出

2 投票
1 回答
6517 浏览
提问于 2025-04-18 12:46

我有一段代码,来自这里,我稍微修改了一下:

#!/usr/bin/env python                                                  

import paramiko                                                        
import select                                                          


server = "192.168.100.100"                                                
port = 22                                                              
name = "root"                                                          
password = "pass"                                                    


def main():                                                            
    client = paramiko.SSHClient()                                      
    client.load_system_host_keys()                                     

    client.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy())
    client.connect(server, port, name, password)                       

    channel = client.get_transport().open_session()                    
    channel.exec_command("/tmp/test.sh")                      

    while True:                                                        
        if channel.exit_status_ready():                                
            break                                                      

        r, w, x = select.select([channel], [], [], 0.0)                
        if len(r) > 0:                                                 
            print channel.recv(1024)                                   

if __name__ == "__main__":                                             
    main()   

其中,test.sh的内容如下:

#!/usr/bin/env bash
while true
do
    echo "Message"
    sleep 1
done

执行这个Python脚本后,CPU的使用率飙升到100%。这意味着这个选择函数并没有等到一个或多个文件描述符准备好进行输入输出操作。根据我的理解,这就是所谓的“忙循环”问题,也就是‘while ... loop’会不断循环,即使没有数据可以读取。请问我该如何实现异步读取远程输出呢?

1 个回答

3

你的问题是你在使用 select 时把超时时间设置成了0秒,这样就不会阻塞了。默认情况下,它会一直等待,直到有数据可用。所以你可以把 select 的超时参数去掉,或者把它改成一个更大的值:

r, w, x = select.select([channel], [], [])

或者

r, w, x = select.select([channel], [], [], 10.0)

你可以通过观察CPU的使用情况,以及在你的 while true 循环后加一个简单的打印语句,来看到这两者的区别。在0.0秒的超时设置下,你会看到它一直在运行。而在更大的超时设置下,你会看到它只运行了一次(而且CPU的使用率也会低很多)。

撰写回答