asyncssh.connect()报timeouterror根本原因是ssh服务未启用或网络不可达,且默认超时仅约15秒、无自动重试;需显式设connect_timeout、检查sshd状态与防火墙、避免阻塞调用。

asyncssh.connect() 为什么总是报 TimeoutError
根本原因通常是目标 SSH 服务未启用或网络不可达,但 asyncssh 默认超时极短(约 15 秒),且不自动重试。它不像 paramiko 那样内置连接池或重连逻辑。
- 显式设置
connect_timeout参数,例如await asyncssh.connect(host, port=22, connect_timeout=30) - 确保目标主机
sshd正在运行,且防火墙放行对应端口(sudo ufw status或iptables -L) - 若用密码认证,确认
PermitRootLogin和PasswordAuthentication在/etc/ssh/sshd_config中已开启 - 避免在协程中混用阻塞调用(如
time.sleep()),改用await asyncio.sleep()
如何并发执行多台服务器的命令而不崩溃
asyncssh 本身是异步的,但并发数过高会触发系统级限制(如文件描述符耗尽、SSH 服务端拒绝新连接),不是代码写错,而是资源没管好。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 用
asyncio.Semaphore控制并发度,例如限制最多 20 个并发连接:sem = asyncio.Semaphore(20),每个connect()前加async with sem: - 不要对每台机器都新建一个独立的 event loop,所有协程共享主线程的 loop
- 命令执行建议用
conn.run()而非conn.create_process(),前者封装了 stdin/stdout/stderr 处理,不易卡死 - 注意
conn.run()返回的是asyncssh.Process对象,需 await 获取结果:result = await conn.run('uptime'),result.stdout才是输出字符串
公钥认证失败:KeyExchangeFailed 还是 PermissionDenied
这两个错误含义完全不同:KeyExchangeFailed 是 TLS 层握手失败(算法不兼容),PermissionDenied 是认证通过但权限不足(比如用户无 shell 或被禁止登录)。
- 遇到
KeyExchangeFailed,优先检查服务端支持的密钥交换算法,可在连接时强制指定:server_host_key_algs=['ssh-rsa', 'ecdsa-sha2-nistp256'] -
PermissionDenied常见于私钥格式不对——asyncssh 不接受 PEM 封装的 OpenSSH 私钥(即带-----BEGIN OPENSSH PRIVATE KEY-----的新版格式),必须转成传统 PEM:ssh-keygen -p -m PEM -f id_rsa - 若用
known_hosts=None跳过主机验证,务必确保环境可信,否则有中间人风险
连接断开后如何自动重连并恢复任务
asyncssh 没有内置重连机制,需要手动捕获异常并封装重试逻辑,但要注意避免无限重试压垮服务端。
- 捕获
asyncssh.DisconnectError和OSError(如连接被拒、网络中断) - 用指数退避重试:第一次等 1 秒,第二次 2 秒,第三次 4 秒……上限建议不超过 60 秒
- 重连后不能直接复用旧的
conn对象,必须重新await asyncssh.connect()并重建 session - 如果任务本身有状态(如上传大文件),需自行实现断点续传逻辑,asyncssh 不提供上传进度或断点支持
conn.ping() 或发送空命令检测活跃性,别等真干活时才发现链路已死。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










