如何在asyncssh中运行进程并持续监听输出、解决缓冲延迟问题
核心原因
该现象并非asyncssh的stdout存在容量上限,本质是远程进程的标准输出缓冲策略导致的:
- 类Unix系统下,程序的标准输出默认会根据输出目标调整缓冲模式:如果输出到交互终端(TTY),则使用行缓冲,每行输出完成后自动刷出;如果输出到管道/非终端场景,默认使用全缓冲,只有缓冲区填满(通常为4KB)或进程退出时才会统一刷出数据。
- 调用asyncssh执行命令时默认不会分配伪终端,远程进程判定为非终端输出场景,因此触发全缓冲机制,就会出现隔一段时间批量输出一批内容、短时间内看起来像输出中断的现象。
解决方案
方案1:创建进程时请求分配伪终端(推荐)
在调用create_process时添加pty=True参数,主动请求SSH服务端分配伪终端,远程进程会自动切换为行缓冲模式,实现逐行输出。
修改后的参考代码如下:
async def watch_process(command): # 注意:原代码中pass是Python关键字,不可作为变量名,建议修改为password等自定义名称 async with asyncssh.connect(host=host, user=user, password=password) as conn: # 新增pty=True参数 async with conn.create_process(command, pty=True) as proc: async for line in proc.stdout: print(f"{host}: {line}") asyncio.run(watch_process(command))
方案2:手动调整远程命令的缓冲模式
如果业务场景不允许开启PTY,可以通过工具包装执行的命令,手动指定行缓冲模式:
- 使用
stdbuf工具:将命令修改为stdbuf -oL 你的原始命令,-oL参数表示将标准输出设置为行缓冲 - 使用
unbuffer工具:将命令修改为unbuffer 你的原始命令,可直接禁用缓冲机制 - 如果远程执行的是Python脚本,可在执行时添加
-u参数,例如python3 -u xxx.py,禁用Python解释器的输出缓冲
内容的提问来源于stack exchange,提问作者LeanMan
相关产品推荐
相关产品推荐

