DSR — 设备状态报告(CSI 5n / CSI 6n)
查询终端状态(5n)或当前光标位置(6n)—— TUI 用以测量终端大小的反向通道。
字节形式
涵盖所有常见的字符串字面量写法,方便正反查找。
\\x1b[
\x1b[5n (status request) \x1b[6n (cursor pos request)\\033[
\033[5n / \033[6n\\e[
\e[5n / \e[6nESC [
ESC [ Ps nhex
1b 5b <Ps> 6e说明
Device Status Report。程序发出请求,终端在 stdin 上回复。\x1b[5n —— 「你还好吗?」。回复:\x1b[0n(就绪)或 \x1b[3n(异常)。常作为启用奇特模式后的存活检查。\x1b[6n(又名 CPR,Cursor Position Report)—— 「光标在哪?」。回复:\x1b[<row>;<col>R。在没有 TIOCGWINSZ 的情况下测算终端大小的经典套路:把光标推到屏幕末端(\x1b[9999;9999H),DSR-6n,解析回复,再还原。现代程序首选 ioctl(TIOCGWINSZ) + SIGWINCH 监听 resize,但缺少该 ioctl 的场景(原始串口、某些 CI 环境)下,DSR-6n 仍是唯一可移植方案。xterm 扩展:\x1b[?6n 返回受 DECOM(origin mode)约束的光标位置。
规范出处: ECMA-48 §8.3.35 (DSR) / xterm-ctlseqs
示例
# Discover terminal size without TIOCGWINSZ:\nstty -echo raw min 0 time 5\nprintf '\033[s\033[9999;9999H\033[6n\033[u'\nIFS=';' read -r -d R esc_row col; stty sane\necho "rows=${esc_row#*[} cols=$col"import sys; sys.stdout.write('\x1b[6n') # reply arrives on stdin in raw modefmt.Print("\x1b[6n")process.stdout.write('\x1b[6n')printf("\x1b[6n"); fflush(stdout); /* parse <row>;<col>R from stdin */在哪里用到
实际会发出该序列的工具——把抽象字节锚定到你已经用过的命令上。
- vim, neovim startup probes`:checkhealth` 在启用块光标 / 鼠标功能前发 `\x1b[6n` 确认光标位置上报可用
- resize(1) (xterm utility)「不用 ioctl 测算终端大小」的经典实现 —— 把光标推到 `\x1b[9999;9999H` 后发 DSR-6n、解析回复并导出 `COLUMNS` 与 `LINES`
- stty -a fallback probes对于无 `TIOCGWINSZ` 的场景(CI runner、串口控制台),裸 `printf '\033[6n'` + 带上限 `read` 是可移植回退方案
- powerlevel10k, starship right-prompts复杂多行提示符用 DSR-6n 校准自身的 wcwidth 估计与终端实际光标推进的偏差
- asciinema, ttyrec — capture DSR replies in the recorded session so playback is dimension-accurate
常见问题
针对这条序列,开发者真正会去搜索的问题的简短回答。
- 我发了
\x1b[6n却收不到回复,哪里出了问题? - 三种常见原因。(1)tty 处于 cooked 模式 —— 回复(
\x1b[<row>;<col>R)抵达 stdin 后被行规程缓存,直到你按 Enter 才送出。切换到 raw 模式或用stty -icanon min 0 time N做带超时的非阻塞读。(2)读取发生在回复抵达 *之前* —— 终端可能要几十毫秒才应答,因此请求务必配上带上限的read(或带超时的select())与回退路径。(3)你在 tmux/screen 内且未开 passthrough —— 复用器代答内部 pane,可能报告自身大小而非宿主终端;要拿宿主信息得开 passthrough 或在复用器接管前直接查询。务必实现 200 ms 超时 +ioctl(TIOCGWINSZ)回退,让缺失的回复不至于挂死程序。 - 检测终端能力时该用 DSR
\x1b[6n还是 DA\x1b[c? - 都不直接答你想要的 —— 它们回答的不是同一个问题。DSR-6n 返回光标位置,可借
\x1b[9999;9999H小技巧测算屏幕大小,但完全不涉及特性支持。DA(\x1b[c) 返回设备属性串以识别模拟器类别(?1;2c、?64;...等)——只是粗粒度能力提示,与具体特性无关。要回答「这个终端支持同步输出 / 焦点事件 / SGR 鼠标吗?」该用 DECRQM(\x1b[?<mode>$p,见decrqm条目),它询问具体 DEC 私有模式并给出 0/1/2/3/4 的明确回答。指纹识别时三者合用:DA 看类别,DECRQM 做每特性门控,没有TIOCGWINSZ的场景下用 DSR-6n 测大小。
终端支持
- xterm
- 支持
- Linux console (fbcon)
- 支持
- macOS Terminal.app
- 支持
- iTerm2
- 支持
- Windows Terminal
- 支持
- cmd.exe / ConPTY
- 支持
- kitty
- 支持
- alacritty
- 支持
- WezTerm
- 支持
- Ghostty
- 支持
- GNOME Terminal
- 支持
- Konsole
- 支持
- tmux
- 支持
- GNU screen
- 支持
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |