当需要同时维护十几台服务器时,你的 SSH 是不是还在排队串行执行?脚本跑起来只能干等半天?今天介绍一个真正意义上的异步 SSH 库——asyncssh,它将稳定、高效的 SSH 连接带入协程时代,让你的运维脚本瞬间加速。
📦 安装与第一个连接
asyncssh 基于 asyncio 生态,安装非常简单:
pip install asyncssh建立第一个连接只需几行代码:
import asyncio, asyncsshasync def check_host(host):async with asyncssh.connect(host, username='root') as conn:result = await conn.run('uname -a')return result.stdout# 实际使用时要放到事件循环中
执行后,你就能拿到类似这样的输出:
Linux myserver 5.4.0-74-generic #83-Ubuntu SMP x86_64🔁 并发执行命令,告别“串行等待”
传统的 paramiko 循环执行任务,N 台服务器就要等待 N 次网络往返。asyncssh 可以同时向多台机器发起命令,总耗时约等于最慢的那一台的时间。
async def fetch_all(hosts):tasks = [check_host(h) for h in hosts]results = await asyncio.gather(*tasks)for h, out in zip(hosts, results):print(f"{h} -> {out.strip()}")# hosts = ['node1', 'node2', 'node3']
运行后,三条结果几乎同时打印出来,而不是排着队等:
node1 -> Linux node1 5.10.0node2 -> Linux node2 5.15.0node3 -> Linux node3 5.8.0
🧠 交互式命令处理不止于“跑一下”
很多运维任务不是单条命令能搞定的,比如 sudo 提权或进入交互式 shell,asyncssh 同样可以轻松应对。
async def sudo_whoami(host):async with asyncssh.connect(host) as conn:stdin, stdout, stderr = await conn.open_session()stdin.write('sudo whoami\n')stdin.write('my_password\n')stdin.write('exit\n')await stdin.channel.wait_closed()return await stdout.read()
调用 sudo_whoami('testbox'),返回结果不再是 “permission denied”,而是珍贵的 root。
🛡️ 文件传输,异步界的一股清流
除了执行命令,文件传输同样是运维的日常。asyncssh 内置了 scp 和 sftp 支持,而且完全非阻塞。
from asyncssh import scpasync def upload_log(host, local_path, remote_path):async with asyncssh.connect(host) as conn:await asyncssh.scp(local_path, (conn, remote_path))# upload_log('backup-srv', '/tmp/app.log', '/var/log/')
传输一个 50MB 的日志文件时,其他并发命令依然在顺畅执行,速度飞快:
[backup-srv] /tmp/app.log -> /var/log/ : 52.3 MB in 1.2s📊 优势对比与实战选型建议
和常见的 paramiko(同步阻塞,简单但并发差)、fabric(对异步支持不原生)相比,asyncssh 最大的优势在于原生 asyncio 集成。面对数百台主机的批量任务时,内存占用和延迟表现都相当出色。
当然,美中不足的是学习曲线稍陡,需要理解事件循环机制。实际选型可以参考:
新项目直接上 asyncssh,性能和管理都能一步到位;
已有大量同步代码,可以用 asyncio.to_thread 桥接,混用过渡也很方便。
💬 写在最后
asyncssh 把 SSH 从“用线程池勉强并发”带进了“优雅的协程时代”。如果你正为大量串行 SSH 任务头疼,不妨试试它,用更少的资源、更快的速度完成同样的工作。
整理不易,如果觉得有帮助,欢迎点赞、转发,你的支持是我们持续输出的动力