Windows 那边接 SSH 的是 cmd 或 PowerShell,不是 Linux 的 shell。绝大多数东西照样能用 —— 但代码助手和别的全屏工具,颜色会不对,除非你在 Windows 那边设一样东西。
撰写于
在 Windows 服务器上,代码助手的面板会变成一块一块的纯色。本来接近黑的背景变成一整片绿,灰色发浑,diff 里加行减行那种很淡的底色全挤成同样的两三种。字都看得清,就是画出来的不是程序想要的那个颜色。btop、lazygit、bat、delta 也一样。
最能说明问题的是:同一个程序连 Linux 或 macOS 服务器就是对的 —— 同一台手机,同一套配色。所以问题不在程序,也不在你选的终端主题。
终端能画大约 1600 万种颜色。程序不会默认你有这个本事,它会去环境里找一个标记;找不到就退回 256 色,再把它想要的每一种颜色换成最接近的那一个。“最接近”就是把接近黑的面板变成一片绿的原因。
连 Linux 和 macOS 的时候,这个标记是 Term 在建立会话时替你设好的。Windows 上做不到:cmd 和 PowerShell 看不懂那一行,而往你的提示符里敲一行只会报错的东西,比颜色不对更糟。所以在 Windows 上,这个标记得在那台机器上设一次 —— 设完以后每个会话都有,用 Term 还是用别的都一样。
到那台 Windows 机器上 —— 直接坐在它前面,或者用 Term 连过去 —— 用你平时 SSH 登录的那个账号,在 PowerShell 里执行:
setx COLORTERM truecolorCOLORTERM 的环境变量,值是 truecolor。机器上别的东西都不动。重连之后颜色还是平的?那是 SSH 服务里还留着旧的环境。用管理员身份的 PowerShell 重启它 —— 这会把那台机器上别的 SSH 会话一起断掉:
Restart-Service sshd不想动账号的环境变量,就写进你的 PowerShell 配置文件。这种只管 PowerShell 的会话 —— 落到 cmd 的会话看不到:
if (-not (Test-Path $PROFILE)) { New-Item -ItemType File -Path $PROFILE -Force } Add-Content $PROFILE '$env:COLORTERM = "truecolor"'
如果这台服务器是你管的,也可以反过来,让它收客户端递过去的设置。Term 本来就会把 COLORTERM 连同语言环境和明暗提示一起递过去,只是服务器得愿意收。加上这一行,然后照上面的办法重启服务:
AcceptEnv LANG LC_* COLORTERM COLORFGBG这条路还有个额外好处:Windows 主机上,每台主机自己的环境变量那一栏要能用,靠的也是它。App 里那一栏底下写的提示就是这个意思。
连上去直接问机器。第一行在 PowerShell 里执行,第二行在 cmd 里:
echo $env:COLORTERM echo %COLORTERM%
什么都不显示,就是还没到 —— 回上一节。显示 truecolor 就是到了,再不对就不是这个设置的事了。
剩下的是 Windows 自己。Windows 服务器上,命令行的输出在送上网之前会先被系统的一层重画一遍,这一层的旧版本不管程序送的是什么,都会把颜色压扁。办法是把 Windows 和它的 OpenSSH 组件升级;升不了的话,看最后一节。
打字时那行灰色的补全,要有 Linux 或 macOS 的 shell 才做得出来,所以这边没有开关可开。PowerShell 自己有历史搜索 —— 快捷键栏上的 ^R 就是它。
生成密钥的时候,主机列表里不会出现 Windows 主机。Windows 存授权公钥的位置不一样、权限规则不一样,管理员账号更是整个换一个文件 —— 一键安装只会悄悄写错文件,然后告诉你成功了。公钥请在 Windows 上自己加。
Term 认出对面是 Windows 的 shell,多出来的键就换成那边要用的:写路径和参数的 \ 和 -,还有 |、$,以及查历史的 ^R。
在主机的高级选项里设的变量,连 Linux 服务器是自己就能到的。Windows 上它走的是上面 COLORTERM 那条路,所以得先让服务器同意收,才到得了。
机器上装了 WSL 的话,把它设成 SSH 登录进去的那个 shell,这一整页就都用不上了。颜色、联想、装公钥、环境变量,全都跟连任何一台 Linux 服务器一样 —— 因为从 Term 这边看,你连的就是 Linux。要改的是 OpenSSH 的默认 shell,在注册表 HKLM:\SOFTWARE\OpenSSH\DefaultShell。
一个提醒,改任何“SSH 登进哪个 shell”的设置都适用:当前这个会话先别关,另开一个试。新 shell 起不来的时候,还连着的那个就是你改回去的路。