终端界面一出问题,很多人的第一反应是改主题、换配色、调终端字体,甚至重装终端,结果折腾半天才发现后端会话根本没起来。dsh-TUI 只是一个显示层,它画不画得出东西,前提是 Harness 那边有会话可画。所以排查顺序建议倒过来:先确认会话是否就绪,再处理渲染。判断标准很直接——如果 Harness 单独跑起来后没有任何就绪提示,界面层面做什么都是白费;只有当 Harness 正常就绪、最简输入也能回显,却仍然出现花屏、卡住、不刷新,才轮到查渲染。
先用无界面方式启动 Harness,确认它能否进入就绪状态并拿到退出码;再回到 dsh-TUI 敲一个最简输入,看字符和响应出现在哪一行。回显正常说明输入链路是通的,此时再改终端尺寸观察是否重绘,就能把「会话没起来」和「渲染层失效」分开。若 Harness 自身启动失败,终端设置与主题都无需再动;日志级别拉高后,两类失败在启动日志里的落点并不相同。
先单独运行 Harness,记录它是否进入就绪状态
这一步的目的是把界面彻底排除掉。在当前终端里直接启动后端进程,不要经过 dsh-TUI,让它的输出打在裸终端上。命令形态通常类似下面这样,具体可执行文件名和参数名以你本地安装为准:
# 在项目目录下,不经过 TUI 直接启动后端
./harness `--config` ./config.toml `--log-level` info
# 记下退出码
echo $?
启动后要观察三件事。第一是有没有停在前台稳定运行,而不是立刻回到 shell 提示符;第二是有没有就绪提示行,常见形态是打印监听的地址或 socket 路径、session 初始化完成、进入等待输入之类的字样,不同实现用词不一样,你需要先看一遍自己的启动输出再定「就绪」长什么样;第三是退出码,正常驻留时不会有退出码,一旦退出,echo $? 返回非 0 就说明后端自身没起来。
失败时重点抄下 stderr 的最后几行,这类片段通常能直接指向原因,例如配置文件某行解析失败、端口或 socket 已被占用、权限不足、依赖的运行时找不到。把这些片段原样记录,后面和 TUI 日志比对时要用。如果这一步就失败,先修 Harness 的启动问题,不要进入下一步。
在 dsh-TUI 里触发一次最简输入,观察回显位置
Harness 能稳定驻留之后,另开一个终端启动 dsh-TUI,让它连到刚才的后端。输入内容要尽量小,一个字符加回车就够,比如敲 a 然后回车,或者用一条最简单的内置命令;不要一上来就粘贴长文本或复杂配置,那会把输入延迟和渲染问题混在一起。
回显可能出现在三个位置:输入行本身(你敲的字符有没有显示出来)、状态栏(有没有连接状态、会话标识变化)、主输出区(后端有没有回一条响应)。三种结果要分开记:
- 字符能显示、后端也有响应:输入链路是通的,会话存在,问题更可能落在绘制时机或终端兼容上,继续看下一节。
- 字符能显示、但没有任何响应:前端接住了按键,但没送到后端或后端没回。此时回到上一步确认 Harness 是否还在前台运行,并检查 TUI 连接的目标地址、socket 路径是否和 Harness 打印的一致。
- 连字符都不显示:界面根本没拿到输入,常见于焦点不在该窗口、终端处于特殊模式、或 TUI 进程已经卡死。先试着用 Ctrl+C 退出,能干净退出说明进程还活着,退出不了则基本判定界面线程已停住。
这一节的产出是一行结论式的记录,例如「输入有回显、后端有响应」,或者「输入无回显、Harness 仍在运行」。有这行记录,下一步的判断才有依据。
改变终端窗口尺寸,看界面是否重绘
很多 TUI 的显示异常只在尺寸变化时暴露:平时看着正常,一拉伸就错位、残影、内容重叠或者干脆空白。操作很简单,拖动终端窗口边缘改变宽高,如果在 tmux 或 screen 里,用 resize-pane 或调整外层终端也可达到同样效果。
缩放前先记下当前画面:状态栏在第几行、内容区显示了什么。缩放后再看同一位置:
- 正常重绘的表现是内容按新宽高重新排布,边框和状态栏跟着移动,光标回到输入行。
- 渲染失效的表现是旧画面残留在上方、新内容叠在旧内容上、边框断裂,或者整个区域变空且长时间不恢复。
- 是否卡住的判断看两处:缩放后继续敲一个字符,看有没有回显;再看进程是否还在消耗 CPU 或完全静默。若按键无回显且进程无反应,属于卡住,而不只是没重绘。
建议把缩放前后各截一张图或抄一段文字描述,因为「错位」这种描述很容易各说各话。做完这一步通常会得到两类结论:尺寸变化能正常重绘,说明渲染路径基本可用,问题更偏会话或输入;尺寸变化必坏,才值得去查终端类型、TERM 变量取值、字符宽度设置这些渲染相关项。
拉高日志级别,收集启动阶段输出
到这一步你需要让两种失败在日志里留下不同的痕迹,而不是靠猜。日志级别一般有三种调法,选你能改的那种即可:命令行参数(如 `--log-level` debug)、配置文件里的日志字段、或者环境变量。改完记得把 Harness 和 dsh-TUI 两边都调高,并且把输出重定向到文件,方便比对:
./harness `--config` ./config.toml `--log-level` debug 2>&1 | tee harness.log
# 另一个终端
dsh-tui 2>&1 | tee tui.log
需要比对的是启动阶段这几类行:Harness 侧有没有出现会话创建、连接接入、进入等待的记录;dsh-TUI 侧有没有出现连接目标地址、握手成功、首帧渲染开始的记录。结论按「谁缺了哪一段」来写,不要写笼统的「日志有报错」:
- Harness 日志里没有会话创建或就绪记录,TUI 侧有连接尝试:问题在会话层,先回到第一节。
- Harness 日志显示会话已建立,TUI 侧有连接成功但没有首帧渲染记录:问题更可能在渲染层,回到第三、四节的观察点。
- 两侧日志都在启动早期就中断,且最后一行相同:多半是配置或环境问题,按那一行报错去查。
这样记录的价值在于,下次再遇到同类现象,你对比的是日志段落的有无,而不是重新走一遍整套猜测。边界上也要清楚:日志能区分失败发生在哪一层,但不等于能定位到具体代码行,真要深入还需要结合具体版本的源码或维护者反馈。