ttyd 网页终端共享故障排查指南:5 类常见报错速查定位
【免费下载链接】ttydShare your terminal over the web项目地址: https://gitcode.com/gh_mirrors/tt/ttyd
ttyd 是一个通过网页共享终端会话的轻量级命令行工具:本地敲一条命令,浏览器里就有一个完整的、支持中文输入和文件传输的终端。听起来省事,但真上线后,端口被占、SSL 握手失败、认证配错、长连接乱断,这些坑一个都少不了。下面把故障按"起不来 → 连不上 → 连上不可用 → 用久了变差"四个阶段收敛归类,每类收 2~3 个高频问题,每个都给可直接敲的命令和验证方法。先对号入座,再动手。
常见故障速查表
| 你看到的现象 | 最可能原因 | 跳转定位 |
|---|---|---|
stderr 打印Address already in use后进程退出 | 7681端口被占用 | §1.1 |
远程访问http://IP:7681超时或拒绝连接 | 防火墙 / 安全组没放行端口 | §2.1 |
| 反代后页面 404,终端空白 | base-path 没配-b | §2.2 |
| 反复弹 Basic 登录框,输对了也不进 | 密码含特殊字符 / 浏览器缓存旧凭据 | §2.3 |
| 能看输出,但敲键盘没反应 | 默认只读,没加-W | §3.1 |
| 终端窗口一闪就关 | 启动命令不存在 | §3.2 |
| 新客户端连不上 | 达到-m上限(预期行为) | §3.3 |
| 放着不动过一会儿就断 | 空闲 ping 超时 | §4.1 |
一、起不来:进程秒退或压根没监听 🔌
先看这一类——进程活不下来,后面的一切都谈不上。三个坑都集中在启动参数这一层,排查成本最低,优先从这里下手。
1.1 一句话定位端口占用
报错原文
bind: Address already in use
原因简析
libwebsockets 在绑定默认端口7681时,发现该端口已经被别的进程占了——可能是一次没退干净的旧 ttyd,也可能是完全不相干的服务。这类报错和 ttyd 本身没关系,纯粹是端口冲突。
解决命令
ss -tlnp | grep 7681这条命令列出占用7681的进程 PID,先搞清楚"是谁占了"。
确认是旧的 ttyd 就干掉它:
kill -9 <PID><PID>换成上一步拿到的进程号,释放端口。
嫌麻烦的话直接换端口更省事:
ttyd -p 8080 bash用-p指定新端口,绕开冲突。
如何验证
重新运行后,终端应打印Listening on port: 8080,浏览器打开http://localhost:8080能加载出终端页面,说明端口已正常监听。
1.2 启动参数写错,进程直接退出
报错原文
ttyd: invalid value for port: abcttyd: invalid credential, format: username:passwordttyd: missing start command
原因简析
这几条都来自 src/server.c 的main():getopt_long解析参数时,任何非法值(端口不是数字、credential 缺冒号、压根没给启动命令)都会fprintf(stderr, ...)然后立刻退出,进程根本进不到监听阶段。
解决命令
最常见两种:
ttyd -c admin:pass123 bash用-c传用户名:密码,注意必须带冒号,ttyd -c admin bash这种缺冒号的写法会直接报 credential 错。
ttyd -p 8080 bash确认命令写全——只写ttyd -p 8080而漏掉后面的bash,就会报missing start command。
如何验证
ttyd -h这条命令打印完整帮助,对照每个选项的格式要求;再正式跑一次,看到Listening on port: ...即启动成功。
1.3 Windows 下 ConPTY 初始化失败
报错原文
ERROR: ConPTY init failed! Make sure you are on Windows 10 1809 or later.
原因简析
Windows 10 1809 之前的内核没有CreatePseudoConsole函数。src/pty.c 里conpty_init()通过动态加载kernel32.dll再查找该符号,找不到就返回 false,进程直接退出。这是系统版本问题,不是 ttyd 的 bug。
解决命令
升级操作系统到 Windows 10 1809 或更高版本,或换一台满足要求的机器。ttyd 侧没有可绕过的开关。
如何验证
重新运行后不再出现 ConPTY 报错,能看到Listening on port: 7681,说明 ConPTY 初始化通过。
进程能活下来之后,接下来最容易出现的问题是"进程明明在跑,浏览器却连不进来",这是下一类。
二、连不上:进程活着,浏览器打不开 🔗
服务端日志清清楚楚写着Listening on port: 7681,可就是访问不到。这一类九成不是 ttyd 的锅,而是它和浏览器之间的那条链路上,有人把路堵了。
2.1 防火墙或安全组挡了端口
报错原文 / 现象
服务端日志显示Listening on port: 7681,但远程浏览器访问http://IP:7681一直转圈,最后超时或"拒绝连接"。
原因简析
本地curl能通、远端不通,基本可以锁定在防火墙或云平台安全组上。端口在系统层被拦,和 ttyd 的配置无关。
解决命令
firewall-cmd --list-ports查看当前放行的端口列表(firewalld 环境),确认7681在不在。
firewall-cmd --add-port=7681/tcp --permanent && firewall-cmd --reload永久放行7681并重新加载规则,让配置生效。
如何验证
在客户端机器上执行:
curl -v http://IP:7681返回 HTTP 200 并带出 HTML 内容,说明端口已真正打通。
2.2 反向代理 base-path 没配
报错原文 / 现象
Nginx 反代 ttyd 后,页面 404,或页面能加载但终端区域一直空白。
原因简析
走反代时请求路径带了前缀(比如/terminal/),而 ttyd 默认按根路径处理,于是返回 404;WebSocket 握手也因路径对不上被拒。src/server.c 里所有端点(/、/ws、/token)都要靠 base-path 统一加前缀。
解决命令
ttyd -b /terminal bash用-b把 base-path 设成反代前缀,ttyd 会自动给所有端点补上该前缀。
如何验证
访问http://IP/terminal/能看到终端页面;打开浏览器 DevTools 的 Network 面板,看到/terminal/ws状态为101 Switching Protocols,即握手成功。
2.3 认证失败被反复弹登录框
报错原文(服务端日志)
WS authentication failed with token: ***
原因简析
src/protocol.c 里check_auth()做的是严格的字符串比对:把客户端Authorization: Basic <b64>头里Basic之后的部分,和-c传入的用户名:密码做 base64 后逐字节比较。密码里含冒号会破坏user:pass的解析,浏览器缓存了旧凭据也会让比对失败,于是反复弹框。
解决命令
ttyd -H X-Auth-User bash用-H把认证交给反向代理:反代在请求头里带上X-Auth-User,ttyd 只校验该头是否存在,彻底绕开 Basic 认证的解析坑。
若仍用-c,先确认密码里没有:,并在无痕窗口里访问一次(清掉缓存的旧凭据)。
如何验证
无痕窗口访问一次即进入终端;服务端日志打印WS /ws - <client_ip>, clients: 1,说明连接已建立。
连上了,但终端用起来不对劲——能看到输出却敲不动、或窗口一闪就没,这是第三类。
三、连上不可用:页面开了,终端却不对劲 🖥️
网络通了、页面开了,但终端要么只读、要么闪退。这类问题最容易让人误以为"连上了就好了",实际上差一个参数或一个命令路径。
3.1 终端只读,敲键盘没反应
报错原文(启动日志警告)
The --writable option is not set, will start in readonly mode
原因简析
ttyd 默认是只读模式,src/server.c 的print_config()会主动打印这条警告。只读意味着能看输出,但INPUT消息会被直接丢弃(src/protocol.c 里if (!server->writable) break;),所以敲键盘没任何反应。
解决命令
ttyd -W bash加-W开启可写。
如何验证
启动日志里不再出现 readonly 警告;浏览器终端里敲whoami、ls能正常执行并回显输出。
3.2 命令不存在,终端一闪而过
报错原文(终端窗口里)
bash: xxx: command not foundexecvp failed
原因简析
src/pty.c 的pty_spawn()用forkpty+execvp拉起命令。命令找不到时execvp返回 -1,子进程_exit(-errno),会话立刻结束,页面表现为"闪一下就关了"。
解决命令
which bash确认命令在 PATH 里确实存在。要用不在 PATH 里的程序,写绝对路径:
ttyd -W /usr/bin/zsh如何验证
终端稳定保持打开不闪退,执行echo $SHELL能返回预期的 shell 路径。
3.3 客户端超限,新连接被拒
报错原文(服务端日志)
refuse to serve WS client due to the --max-clients option.
原因简析
这是预期行为,不是故障。src/protocol.c 在连接过滤阶段检查client_count == max_clients,达到上限直接拒绝新连接,保护服务端不被压垮。
解决命令
ttyd -m 20 bash按实际并发需求调大上限。如果上限是故意设的(比如做演示只想给少数人),那"被拒"本身就是正确结果,不用修。
如何验证
日志里clients:计数能涨到 20 而不被拒;第 21 个连接仍会被拒——这正符合-m 20的预期。
跑短期演示没问题,但要是挂着长期运行,时间一长就会暴露另一类更隐蔽的毛病。
四、用久了变差:跑得越久越不对劲 📉
这一类没有明显的报错,表现是"时好时坏"。多数和空闲超时、进程生命周期有关,优先怀疑网络层,再回头查 ttyd 参数。
4.1 长连接被空闲断开
报错原文 / 现象
终端放着不动,过一会儿突然断开,刷新才能重连。
原因简析
libwebsockets 的 retry 策略带secs_since_valid_ping(默认 5 秒)和secs_since_valid_hangup(默认 ping 间隔 + 7 秒),超时就主动断开;NAT 超时、WiFi 休眠也会让底层 TCP 悄悄断掉。这类"过一阵就断"通常是网络层心跳问题,不是 ttyd 自身。
解决命令
ttyd -P 10 bash用-P把 WebSocket ping 间隔从默认 5 秒调到 10 秒(src/server.c 里retry.secs_since_valid_ping = interval),减少心跳包数量。若调了还频繁断,优先查网络而不是继续改 ttyd。
如何验证
ss -tlnp | grep 7681确认监听正常;终端放置 30 分钟以上不再自动断开,客户端 DevTools 里 WS 连接状态保持 101。
4.2 客户端全退后进程还占着端口
报错原文 / 现象
所有浏览器都关了,ttyd 进程还在跑,端口一直被占着。
原因简析
默认行为就是"最后一个客户端断开后进程继续存活",方便复用。只有--once(只接一个客户端,断开即退)和--exit-no-conn(全部断开即退)才会主动退出(src/protocol.c 里LWS_CALLBACK_CLOSED处理)。
解决命令
ttyd -o bash一次只接一个客户端,断开即退出,适合临时演示。
ttyd -q bash所有客户端断开后退出,适合需要复用端口、按连接释放的场景。
如何验证
关闭所有浏览器标签后执行:
ps aux | grep ttydttyd 进程消失;日志打印exiting due to the --once/--exit-no-conn option.,说明生命周期符合预期。
自查无果:收齐信息再找人,省一半时间
上面四类覆盖了绝大多数现场问题。如果你的情况没被覆盖,别急着问人——先把信息收齐再去找维护者或社区,来回追问才是最耗时间的。
先记下这几项
ttyd -v拿到版本号,这是排查的第一手依据。
uname -a记录操作系统与内核版本。
ttyd -d 1 bash用-d 1把日志级别降到只输出错误(src/server.c 里-d设置 libwebsockets 日志级别,数值越小越安静),把完整 stderr 截下来。
再补上浏览器 DevTools 里 Console 和 Network 的报错截图,以及完整的启动命令(含所有参数)。
搜索关键词建议
- 直接搜报错原文,如
ttyd "Address already in use"、ttyd "WS authentication failed" - 加参数名搜,如
ttyd -b base-path 404 - 在官方 Issue 区搜同样报错,网络与认证类问题多数有现成答案
官方渠道
- 项目 Issue 区:标题写清现象("连不上" / "认证失败"),正文贴全"版本 + 系统 + 启动命令 + 日志"四件套,别只写一句"不工作"
- 社区讨论:描述里附上
ttyd -h的输出,方便对方确认你当前版本支持的参数集
提 Issue 前的信息清单
ttyd -v版本号uname -a系统输出- 完整启动命令
-d 1日志关键片段(20 行左右)- 浏览器名称 + 版本 + 控制台报错截图
- 是否走反代 / 防火墙,若是附上反代配置片段
一份材料齐了再发出去,维护者基本能直接定位,省掉来回追问的功夫。
【免费下载链接】ttydShare your terminal over the web项目地址: https://gitcode.com/gh_mirrors/tt/ttyd
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考