2.2 KiB
2.2 KiB
WebSSH 终端输入回显延迟修复
日期: 2026-05-26 变更摘要: 修复 WebSSH 终端输入字符不即时显示的问题 — 将 async-for (readline) 改为 read() + 降低 bufsize
动机
- 用户在终端输入字符后,字符不会即时显示(echo 延迟),必须按 Enter 后才一次性出现
- 根因:
async for data in shell.stdout内部调用readline()→readuntil('\n'),会缓冲所有数据直到遇到换行符 - 交互式终端中,单字符 echo 永远不包含换行符,导致所有输入字符被缓冲直到用户按 Enter
变更内容
server/api/webssh.py — 2处修改
修改1: _read_shell_output() 函数 — 消除 readline 缓冲
- 旧:
async for data in shell.stdout:(内部 readline,等换行才 yield) - 新:
while not shell.stdout.at_eof(): data = await shell.stdout.read(4096)(有数据即返回) read(n)使用exact=False,只要缓冲区有数据就立即返回(最多 n 字节),不等换行
修改2: create_process() 调用 — 降低 bufsize
- 旧:
conn.create_process(term_type="xterm-256color", term_size=(24, 80))(默认 bufsize=128KB) - 新:
conn.create_process(term_type="xterm-256color", term_size=(24, 80), bufsize=4096) - 两处 create_process(主连接 + 失效重试连接)均添加
bufsize=4096 - 4KB 缓冲区足够单次交互 echo,同时大幅降低延迟
技术分析
asyncssh 数据流路径:
async for data in shell.stdout
→ SSHStreamProcess.__aiter__()
→ SSHStreamSession.aiter()
→ readline()
→ readuntil('\n') ← 阻塞直到换行符
修复后路径:
while not shell.stdout.at_eof():
data = await shell.stdout.read(4096)
→ SSHStreamSession.read(4096, exact=False) ← 有数据即返回
涉及文件
server/api/webssh.py— WebSSH WebSocket 处理(2处修改)
是否需迁移/重启
- 需重启后端(webssh.py 修改)
- 前端无改动
验证方式
- 打开 terminal.html?server_id=8 → WebSocket 保持 OPEN,状态显示「已连接」
- 输入
whoami→ 字符即时显示(不等 Enter),按 Enter 后立即显示root - 后端日志无
shell creation failed错误 - 终端交互流畅,无 echo 延迟