Ubuntu 18.10 终端光标从方块改成竖线:TaoToken 配置骨架与验证
1. Ubuntu 18.10 终端光标为什么是方块怎么改成竖线Ubuntu 18.10 默认终端GNOME Terminal在不少主题和字体组合下光标会显示成一个实心方块。这个方块光标在行尾时会直接盖住当前字符尤其是你写 Shell 脚本、调 Python 缩进、或者对着日志逐字核对的时候方块一压上去那个字符到底是l还是1、是,还是.全靠猜。这个问题在 Ubuntu 18.10 上尤其明显因为它自带的 VTE 版本对光标形状的默认处理就是块状而且很多网上搜到的“改光标”教程要么只讲 GUI 设置要么给的转义序列不完整重启终端后又变回方块。我试过在 Ubuntu 18.10 上把方块光标改成竖线bar核心思路其实就两条一是用终端转义序列告诉 VTE 把光标渲染成竖线二是把这个序列写进 shell 启动文件让每次开终端都自动生效。转义序列\x1b[5 q表示闪烁竖线\x1b[6 q表示稳定竖线这两个是 DECSCUSRDEC Set Cursor Style标准里的写法GNOME Terminal 底层的 VTE 是认的。但光写进~/.bashrc还不够因为有些终端模拟器在启动时会用自己的配置覆盖掉所以还得配合settings.json或config.toml这类配置骨架把光标形状固定下来。这篇文章面向的是刚装好 Ubuntu 18.10、或者一直在用方块光标但不知道怎么改的开发者。我会先讲清楚光标形状的几种取值和对应转义码然后给出可以直接复制的~/.bashrc片段、GNOME Terminal 的settings.json骨架以及如果你用其他终端比如 Tilix、Alacritty时的config.toml写法。最后会带你验证改完重开终端光标是不是真的变成竖线了以及如果没变该从哪几个地方排查。整个过程不需要装额外软件也不需要改系统级配置普通用户权限就能完成。2. TaoToken 前置为什么改光标前先确认终端环境在动手改光标之前有一个容易被忽略的前置动作确认你当前终端到底跑在什么环境里。Ubuntu 18.10 默认是 GNOME Terminal但很多人会装 Tilix、Terminator、Alacritty或者通过 SSH 连到远程机器。不同终端对 DECSCUSR 转义序列的支持程度不一样GNOME Terminal 和 Tilix 支持得比较好Alacritty 则更推荐在config.toml里直接写cursor.style。如果你在 SSH 会话里改转义序列是发给本地终端模拟器的所以改远程的~/.bashrc不一定能影响本地光标形状。这里顺便说一个我平时调试终端配置时用的工具TaoToken。它本身是一个大模型 API 聚合平台但我在调终端配置、写 Shell 片段、排查转义序列为什么没生效的时候会用它来快速问一些 VTE 版本差异、DECSCUSR 参数含义之类的问题。它的模型对话入口在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 你可以直接在里面问“Ubuntu 18.10 VTE 支持哪些光标形状转义码”它会给出比翻 StackOverflow 更结构化的回答。如果你后面要长期写脚本、做 Agent 开发也可以看它的 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。不过要说明的是改光标这件事本身不需要任何 API Key也不需要联网。TaoToken 在这里的角色是“查文档、问参数”的辅助工具不是必须步骤。你完全可以只看下面的配置片段直接操作。我把它放在前置章节是因为很多人在改终端配置时遇到报错第一反应是去搜但搜到的答案版本对不上反而绕远路。用模型对话把“你的终端类型 VTE 版本 想要的形状”描述清楚能省不少时间。确认终端类型的命令很简单echo $TERM如果输出xterm-256color说明是兼容 xterm 的终端DECSCUSR 序列大概率可用。再看一下 GNOME Terminal 版本gnome-terminal --versionUbuntu 18.10 一般带的是 GNOME Terminal 3.30 左右VTE 0.52这个版本对\x1b[5 q和\x1b[6 q是支持的。如果你用的是 Tilix它底层也是 VTE同样支持。Alacritty 不吃这套转义序列得改config.toml这个后面会单独给骨架。3. 可复制配置bashrc 片段与 settings.json/config.toml 骨架3.1 先搞清楚光标形状的转义码对照DECSCUSR 标准里ESC [ Ps SP q这个序列的Ps参数决定光标形状。SP是空格q是结束符。在 Shell 里用echo -e写就是\x1b[Ps q。具体取值如下Ps 值光标形状说明0默认跟随终端配置1闪烁方块blinking block2稳定方块steady block3闪烁下划线blinking underline4稳定下划线steady underline5闪烁竖线blinking bar6稳定竖线steady bar你要的“竖线”就是 5 或 6。我个人推荐用 6稳定竖线因为闪烁竖线在长时间盯着屏幕时反而容易分心而且有些终端在失焦时闪烁会停看起来像卡住了。稳定竖线在行尾定位字符最清楚。3.2 写入 ~/.bashrc 的片段打开~/.bashrcnano ~/.bashrc拉到文件末尾加上这一段# 将终端光标设置为稳定竖线steady bar # 仅在交互式 shell 中执行避免影响 scp/rsync 等非交互场景 if [[ $- *i* ]]; then echo -ne \x1b[6 q fi这里加[[ $- *i* ]]判断是有原因的。如果你不加判断直接把echo -ne \x1b[6 q写在.bashrc末尾那么每次非交互式调用 bash比如scp、rsync、cron里跑脚本都会往输出里塞一段转义序列虽然大多数时候无害但在某些管道场景下会污染输出。加上交互式判断后只有你手动开终端时才发这个序列。保存退出后让当前终端立即生效source ~/.bashrc这时候光标应该马上变成竖线。如果没变先别急看第 5 节的排查。3.3 GNOME Terminal 的 settings.json 骨架GNOME Terminal 从 3.28 开始支持通过gsettings或 dconf 改光标形状但更彻底的方式是直接写 profile 配置。Ubuntu 18.10 上 GNOME Terminal 的配置存在 dconf 里你可以用gsettings命令改# 列出所有 profile gsettings get org.gnome.Terminal.ProfilesList list # 假设你的 profile ID 是 b1dcc9dd-5262-4d8d-a863-c897e6d979b9 # 设置光标形状为 ibeam竖线 gsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/ cursor-shape ibeam # 设置光标闪烁为 false gsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/ cursor-blink-mode offcursor-shape的可选值有block、ibeam、underline。ibeam就是竖线。这个设置是持久化的重启终端后依然有效而且优先级比.bashrc里的转义序列高。也就是说如果你同时用了gsettings和.bashrc最终显示的是gsettings的结果。所以如果你改了gsettings发现.bashrc不生效是正常的。如果你想把配置导出成settings.json做备份或迁移可以用dconf dump /org/gnome/terminal/legacy/profiles:/ gnome-terminal-settings.json导出的文件里会有类似这样的结构[/] cursor-shapeibeam cursor-blink-modeoff fontUbuntu Mono 13恢复的时候用dconf load /org/gnome/terminal/legacy/profiles:/ gnome-terminal-settings.json3.4 Alacritty 的 config.toml 骨架如果你用的是 Alacritty它不认 DECSCUSR 转义序列得改~/.config/alacritty/alacritty.yml旧版或~/.config/alacritty/alacritty.toml新版。Ubuntu 18.10 时期 Alacritty 还用 YAML但为了兼容现在的新版这里给 TOML 写法[cursor] style Beam blinking Offstyle可选Block、Underline、Beam。Beam就是竖线。blinking可选Off、On、Always。改完保存Alacritty 会自动重载配置光标立刻变竖线。3.5 Tilix 的配置方式Tilix 底层是 VTE所以.bashrc里的转义序列对它有效。但 Tilix 自己也有 GUI 设置打开 Tilix点右上角菜单 → Preferences → Profile → Cursor把 Cursor Shape 改成I-BeamBlink 改成Off。这个设置会覆盖.bashrc的转义序列所以如果你在 Tilix 里改了没效果检查一下这里。4. 验证请求重开终端确认光标变成竖线配置写完后验证分三步。第一步关掉当前终端窗口重新开一个。不要只source ~/.bashrc因为有些终端在启动时会重新应用自己的 profile 设置source只能临时改当前会话。重开才能验证持久化是否生效。第二步在空提示符下观察光标。如果光标是一个细竖线并且在行尾时不会盖住字符说明成功了。你可以输入一段文字然后把光标移到中间看竖线是不是插在字符之间而不是盖在字符上面。第三步用命令确认当前终端的光标形状设置。GNOME Terminal 下可以查gsettings get org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:$(gsettings get org.gnome.Terminal.ProfilesList default | tr -d )/ cursor-shape如果输出ibeam说明 profile 层面已经是竖线。如果输出block说明gsettings没改成功回去检查 profile ID 有没有写错。再验证一下.bashrc的转义序列有没有发出去。开一个终端输入echo -ne \x1b[6 q | cat -v你应该看到^[[6 q。这说明转义序列本身是合法的。如果cat -v显示乱码说明你的 shell 或终端对\x1b的处理有问题检查一下是不是用了sh而不是bash。还有一个更直接的验证方法在终端里运行一个会持续输出的命令比如ping localhost然后观察光标。如果光标是竖线且在行尾不遮挡字符就说明生效了。按CtrlC停掉。如果你在 SSH 会话里验证注意转义序列是发给本地终端模拟器的。也就是说你在远程服务器上改~/.bashrc重连后本地终端的光标形状会变但远程服务器的终端类型$TERM必须是xterm-256color或类似支持 DECSCUSR 的值。如果远程$TERM是dumb或vt100转义序列会被忽略。5. 本篇常见错排查改了没生效、光标闪烁、SSH 下失效5.1 改了 .bashrc 但重开终端还是方块最常见的原因是gsettings里的cursor-shape还是block而且它的优先级高于.bashrc的转义序列。GNOME Terminal 在启动时会先应用 profile 设置然后才执行.bashrc但 VTE 对光标形状的处理是“后设置的生效”而 profile 设置是在 shell 启动前就注入的所以实际上 profile 会覆盖掉 shell 里发的转义序列。解决办法就是按 3.3 节把gsettings的cursor-shape也改成ibeam。另一个原因是.bashrc里那段代码被放在了return之后或者被其他条件判断挡住了。检查一下你加的位置是不是在文件最末尾并且没有被if [ -z $PS1 ]; then return; fi这类语句提前返回。Ubuntu 默认的.bashrc开头就有非交互式判断如果你把代码加在它前面非交互式场景会执行加在后面交互式场景才会执行。建议就加在文件最末尾。5.2 光标变成竖线但一直闪烁你用的可能是\x1b[5 q闪烁竖线而不是\x1b[6 q稳定竖线。把.bashrc里的5改成6即可。如果改了还闪检查gsettings的cursor-blink-mode是不是on改成offgsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:PROFILE_ID/ cursor-blink-mode off5.3 SSH 到远程服务器后光标变回方块这是因为本地终端模拟器在 SSH 会话建立时可能会根据远程的$TERM重置光标形状。解决办法是在本地.bashrc里也加上转义序列或者在 SSH 配置里加RequestTTY force。更简单的做法是在远程服务器的.bashrc里也加上echo -ne \x1b[6 q这样每次 SSH 登录后远程 shell 会再发一次转义序列给本地终端。注意远程$TERM要支持用export TERMxterm-256color可以强制设置。5.4 在 tmux 或 screen 里光标形状不对tmux 会拦截转义序列默认不把 DECSCUSR 传给外层终端。你需要在~/.tmux.conf里加set -g terminal-overrides ,xterm*:Ss\E[%p1%d q:Se\E[2 q然后tmux kill-server重启 tmux。这样 tmux 就会把光标形状序列透传给 GNOME Terminal。screen 类似但配置更麻烦建议直接用 tmux。5.5 用了 zsh 或 fish 怎么办.bashrc只对 bash 生效。如果你用 zsh把同样的echo -ne \x1b[6 q加到~/.zshrc末尾。fish 的话加到~/.config/fish/config.fish语法是echo -ne \x1b[6 q但 fish 的echo不支持-e得用printfprintf \x1b[6 q5.6 终端里显示\x1b[6 q这串字符而不是生效说明你的echo没有解析-e或者你用的是sh而不是bash。Ubuntu 18.10 的/bin/sh默认是 dashdash 的echo不支持-e。解决办法是用printf代替printf \x1b[6 qprintf在所有 POSIX shell 里都解析反斜杠转义。把.bashrc里的echo -ne换成printf更稳妥。6. 后续怎么把这套配置用到日常开发里光标改成竖线只是终端个性化的一小步但它的收益很直接读代码、对日志、调缩进的时候眼睛不用再跟方块光标打架。上面给的.bashrc片段和gsettings命令你可以直接复制到自己的 Ubuntu 18.10 上重开终端就能看到效果。如果你用的是 Alacritty 或 Tilix对应的config.toml和 GUI 设置也给了按自己的终端类型选一条路走就行。后面如果你要批量管理多台机器的终端配置可以把dconf dump导出的settings.json和.bashrc片段一起放进 dotfiles 仓库用 GNU Stow 或 chezmoi 做同步。这样换机器的时候不用重新调光标形状。如果你在写 Shell 脚本时遇到转义序列不生效、或者想确认某个 VTE 版本支持哪些 DECSCUSR 参数可以用 TaoToken 的模型对话快速查一下https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。需要长期做终端工具链开发、或者写 Agent 脚本的话Coding Plan 的入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面有针对代码补全和脚本生成的额度方案。API 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content Key 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。这些链接按需取用改光标本身不需要它们。最后提醒一句如果你在.bashrc里加了转义序列后发现scp或rsync报错说“protocol error”或输出里混入了奇怪字符检查一下是不是忘了加[[ $- *i* ]]判断。非交互式场景下往 stdout 写转义序列确实会干扰某些工具的输出解析。加上判断就能避免。