先说清楚:为什么我要在 Windows 上折腾一个“原生”的 zsh
标题里那句“不是在 WSL 子系统下”,其实是我自己被问得最多的一句话。很多朋友看到我终端里跑着 zsh、装着 oh-my-zsh、主题是 powerlevel10k,第一反应就是“你这不是 WSL 吗”。还真不是。我机器上确实有 WSL,但那个窗口是另一个 profile,我这里说的这套 zsh,是跑在 Windows 自己的进程空间里的,不需要虚拟机、不需要 Linux 内核、不需要开 Hyper-V,双击一个终端就能起来。
那么问题来了:Windows 下没有原生 zsh 的官方版本,zsh 是 POSIX 世界的产物,怎么才能在 Windows 上“真正”跑起来?答案是通过POSIX 兼容层,最主流的两条路是MSYS2和Cygwin。它们做的事情说白了就是:在 Windows 上模拟出一套 Unix 的文件系统视图、进程模型和终端语义,然后把 Linux 上编译好的那套 shell 工具链(zsh、bash、coreutils、git、vim……)重新编译成能在 Windows 上直接执行的 exe。你装完之后,zsh.exe就是一个货真价实的 Windows 可执行文件,任务管理器里能看到它,Windows Terminal 能直接把它当成一个 shell profile。
这篇东西写给谁看?三类人比较合适。第一类是被 WSL 的磁盘占用、内存开销、跨文件系统 IO 慢折腾过的开发者;第二类是需要长时间 SSH 到 Linux 服务器、希望本地终端操作习惯和远端保持一致的人;第三类就是纯折腾党,想让 Windows 的终端看起来、用起来都接近 Linux 那套手感。不管你是哪一类,下面这套流程你跟着走一遍,基本能落地。我会把每一步“为什么这么选”讲清楚,也会把踩过的坑一并交代。
1. 路线选型:MSYS2、Cygwin、Git Bash 到底选哪个
1.1 三者到底差在哪,不是随便挑一个就行
很多人以为这三个差不多,其实定位差别挺大。Cygwin是最老牌的 POSIX 兼容层,它的目标是“把 Unix 程序原样搬到 Windows”,实现得最完整,连 fork() 都模拟出来了,但代价是它的 DLL 层比较厚重,路径模型是/cygdrive/c/...,和 Windows 的互操作总觉得隔了一层。MSYS2是基于 Cygwin 早期代码分出来的一个分支,它的核心诉求是“让 Windows 下的原生开发工具链能用”,所以它的路径模型改成了/c/...,和 Windows 程序的互相调用更自然,而且它用 pacman 管包,装东西的体验和 Arch Linux 几乎一模一样。
Git for Windows 自带的 Git Bash又是另一回事,它其实内置了一个精简版的 MSYS2 运行时,但只带了一小撮工具,包管理是没有的。你想在里面加装 zsh,理论上是把 zsh.exe 和相关 DLL 拷进去,实践中非常容易因为 DLL 版本错位炸掉,我不推荐。
所以结论很清楚:想在 Windows 上有长期可维护的原生 zsh,选 MSYS2。它有包管理、有活跃社区、有多个工具链环境(MSYS、UCRT64、MINGW64、CLANG64),zsh 就装在 MSYS 环境里,和 Windows 原生程序混着用也不别扭。
1.2 一个必须提前说清楚的性能前提
选 MSYS2 之前,你得接受一个现实:它不是 Linux,fork 性能天生差一截。MSYS2 的进程创建本质上还是要走 Windows 的 CreateProcess,虽然比早年 Cygwin 快很多,但和 Linux 上的fork()还是没法比。这意味着什么呢?意味着你在 zsh 里写一个循环里跑一万次子命令的脚本,会明显比 Linux 慢;意味着 oh-my-zsh 启动时那一堆git status、date、uname的子进程调用,是启动耗时的主要来源。
知道这一点之后,你的优化方向就明确了:减少子进程调用、减少启动时的探测、用 zsh 内建函数替代外部命令。后面我在讲 powerlevel10k 配置和插件裁剪时会具体说。很多人装完觉得“怎么这么卡”,其实不是 MSYS2 不行,是他默认开着几个重量级插件加一个每次都去读 git 状态的提示符,慢是必然的。
1.3 和 WSL 方案的取舍逻辑
顺便把 WSL 这条路的取舍也讲明白,免得你选错工具。WSL 的优势是“真的是 Linux 内核”,包管理完整、docker 能跑、文件系统语义一致、性能接近原生;劣势是它是一套独立的文件系统,你在 WSL 里访问C:\走的是 9p 协议,跨盘 IO 很慢,反过来 Windows 访问 WSL 的文件也一样。另外它的内存是动态占用的,虽然新版能限制,但总归多一层。
MSYS2 的优势是“同一套文件系统”,你在 zsh 里cd /c/Users/xxx/Projects和资源管理器里看到的完全是同一份文件,没有拷贝、没有同步、没有双份磁盘占用;启动一个终端大概零点几秒,没有虚拟机那层开销。劣势就是前面说的 fork 性能,以及部分 Linux 专属的东西(比如 systemd、更完整的信号语义)用不了。
我的实际做法是两个都留着:需要跑 docker、跑需要真 Linux 内核的东西时用 WSL;日常写代码、SSH、做文件整理、跑 git 时用 MSYS2 的 zsh。两套 profile 都在 Windows Terminal 里,切换成本为零。
2. 装前准备:MSYS2 安装与镜像源提速
2.1 下载与安装路径,这一步埋的坑最多
去 msys2.org 下载msys2-x86_64-*.exe,这个不用纠结版本号,装完第一件事就是更新,版本新旧无所谓。
但安装路径必须说三遍:不要有空格,不要有中文,不要放在 OneDrive 同步目录里。默认的C:\msys64就是最好的选择,直接用它。为什么?因为 MSYS2 里大量的脚本、Makefile、configure 文件在传递路径时是不加引号的,路径里一旦有空格,/c/Program Files/msys64会被拆成两个参数,报错信息还特别隐晦,你根本想不到是路径问题。中文路径则是编码问题,某些工具在 GBK 和 UTF-8 之间来回转,会出现“文件名乱码”或者“找不到文件”的诡异现象。
还有一条很多人忽略的:把 MSYS2 安装目录加到 Windows Defender 的排除项里。Windows Defender 的实时扫描对 MSYS2 这种“大量小文件频繁读写”的场景特别敏感,实测把C:\msys64加排除后,pacman安装包的速度能有肉眼可见的提升,zsh 启动也会快一些。操作路径是“Windows 安全中心 → 病毒和威胁防护 → 管理设置 → 排除项 → 添加文件夹”。
2.2 首次更新与镜像源替换的完整顺序
装完之后从开始菜单打开 “MSYS2 MSYS” 那个终端(注意不是 UCRT64,也不是 MINGW64,我们要用的是 MSYS 环境)。第一件事是更新,但国内直连官方源会慢到让人怀疑人生,所以顺序应该是先换源,再更新。
改源的位置在/etc/pacman.d/下面,你会看到mirrorlist.msys、mirrorlist.mingw、mirrorlist.ucrt64这几个文件(不同版本略有差异)。MSYS2 的规则是:mirrorlist.msys管的是 MSYS 环境自己的包,mirrorlist.mingw/mirrorlist.ucrt64管的是各个工具链的包。zsh 属于 MSYS 环境的包,所以关键是改mirrorlist.msys。
我习惯用清华的源,在文件最上面加这两行:
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch Server = https://mirrors.ustc.edu.cn/msys2/msys/$arch$arch是变量,pacman 会自己替换成x86_64,不用你手动改。如果你也想让后续装 mingw 工具链快一点,就在mirrorlist.mingw顶部加:
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/$repo/改完保存,然后执行更新:
pacman -Syu这里有个关键点:第一次-Syu会提示你关闭终端重新打开,因为 pacman 自己要被更新。这不是报错,是正常流程。关掉窗口、重新打开、再执行一次pacman -Su,才算更新完。很多人第一次装就是因为没重开,后面装什么都说“版本冲突”。
2.3 密钥环报错的应急处理
换源或者更新时,最常见的一类报错是签名相关的,比如提示invalid or corrupted package、PGP signature could not be verified,或者key ... is unknown。这基本不是源的问题,而是本地密钥环过期或损坏了。处理方式很直接,重建密钥环:
rm -r /etc/pacman.d/gnupg pacman-key --init pacman-key --populate msys2 pacman -Sypacman-key --init那一步会花点时间,因为它要在本地生成一个 GPG 密钥对,慢是正常的,别以为是卡死了。跑完之后再pacman -Syu基本就顺了。
还有一种情况是提示某个包“已存在但不在数据库中”,这通常是上次更新中断留下的残骸。可以先用pacman -Qk检查一遍文件完整性,再用pacman -S --overwrite '*' 包名强制覆盖。这类问题不常遇到,但遇到了知道怎么查比临时搜要快得多。
3. 把 zsh 真正装进去,并让它成为默认 shell
3.1 安装 zsh 本体和几个必备搭档
环境更新干净之后,装 zsh 就一行:
pacman -S zsh但光装 zsh 是不够的,我建议顺手把这几样一起装上,它们是你后面所有体验的基础:
pacman -S zsh zsh-completions git curl wget vim nano less tree \ unzip zip openssh man-db man-pages这里每一项都有理由。zsh-completions提供大量补全定义,没有它你会发现很多命令的 Tab 补全很弱;git是 oh-my-zsh 的强依赖,没有 git 的时候 oh-my-zsh 安装脚本会直接退出;curl/wget是你下载 oh-my-zsh 和插件用的;man-db和man-pages决定了man ls这种命令能不能用,MSYS2 默认是不装的,不装的话你查文档只能靠--help。
装完验证一下:
which zsh zsh --versionwhich应该输出/usr/bin/zsh,版本号应该在 5.8 以上。如果which找不到,说明 PATH 有问题,检查一下是不是环境变量被 Windows 的某些工具改乱了。
3.2 让 MSYS2 启动时自动进 zsh
装好之后直接敲zsh就能进去,但每次手动敲太麻烦。官方那几个启动快捷方式(MSYS2 MSYS、MSYS2 UCRT64)默认都是起 bash,我们要改成自动跳 zsh。
最稳的方式是在~/.bashrc末尾加一段判断,只在交互式终端且当前不是 zsh 时才切换:
if [[ $- == *i* ]] && [ -z "$ZSH_VERSION" ]; then exec zsh fi$-是当前 shell 的选项标志,包含i说明是交互式会话;$ZSH_VERSION为空说明现在还没进 zsh。这两个条件一起判断,可以避免脚本执行、ssh 远程命令等非交互场景被误伤——这一点很重要,如果你不加交互式判断,某些自动化脚本调用 MSYS2 的时候会被强行切成 zsh,然后行为全乱。
改完之后重新打开 MSYS2 MSYS 窗口,应该直接就是 zsh 的提示符了。第一次进 zsh 会有一个zsh-newuser-install的交互式配置向导,按q退出就行,我们要自己配。
3.3 在 Windows Terminal 里加一个专属 profile
我强烈建议在Windows Terminal里用这套 zsh,而不是用它自带的那个控制台窗口。Windows Terminal 支持 GPU 渲染、真彩色、更好的字体和光标,体验差一个档次。打开 Windows Terminal 的设置(JSON 模式),在profiles.list里加一段:
{ "guid": "{8a1b2c3d-4e5f-6789-abcd-ef0123456789}", "name": "MSYS2 zsh", "commandline": "C:\\msys64\\usr\\bin\\zsh.exe -l -i", "startingDirectory": "C:\\msys64\\home\\你的用户名", "icon": "C:\\msys64\\msys2.ico", "font": { "face": "MesloLGS NF" }, "colorScheme": "One Half Dark", "hidden": false }几个细节必须解释。guid是一串你自己造的 UUID,格式对了就行,保证不和别的 profile 重复;-l -i两个参数不能省,-l让 zsh 按登录 shell 启动,这样它才会去读/etc/zprofile,而 MSYS2 正是靠这个文件把 PATH 初始化好的,省掉-l你会发现一堆命令找不到;startingDirectory建议写 MSYS2 的 home 目录,而不是 Windows 的C:\Users\xxx,原因后面讲 HOME 的时候会说。
如果你按照上面配了zsh.exe -l -i之后发现 PATH 还是不全,那就改成走 bash 中转:
"commandline": "C:\\msys64\\usr\\bin\\bash.exe -lc \"exec zsh -l -i\""这条命令让 bash 先以登录模式把环境变量铺好,再把自己替换成 zsh,几乎能绕过所有 PATH 相关的玄学问题。我在几台机器上验证过,这种写法兼容性最好。
4. 把 zsh 变成“顺手”的 zsh:oh-my-zsh、主题与插件
4.1 oh-my-zsh 的国内安装姿势
裸 zsh 能用,但补全、提示符、插件都得自己写,效率太低。oh-my-zsh 仍然是目前生态最成熟的框架,虽然它启动偏慢,但可配置性够。官方安装脚本走的是raw.githubusercontent.com,国内网络经常拉不动,所以别用那个脚本,直接走镜像仓库:
git clone --depth=1 https://gitee.com/mirrors/oh-my-zsh.git ~/.oh-my-zsh cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc--depth=1只拉最新一次提交,速度快很多,oh-my-zsh 那种历史包袱巨大的仓库,全量 clone 意义不大。第二步是把模板.zshrc拷到 home 目录,这样你就有了一个可编辑的配置文件。
这时候要注意,MSYS2 里的~到底指向哪里。默认情况下~是/home/你的用户名,实际路径是C:\msys64\home\你的用户名,也就是说你的 dotfiles 全在这个目录下。这有好处也有坏处:好处是隔离干净,Windows 侧的软件不会来乱翻;坏处是你和 Windows 原生的编辑工具、备份工具共享配置会比较麻烦。
如果你希望 HOME 和 Windows 用户目录一致,让.zshrc直接躺在C:\Users\你的用户名下面,可以改/etc/nsswitch.conf:
db_home: windows加上这一行之后重启终端,echo $HOME应该输出/c/Users/你的用户名。这么改的实际收益是:你的.zshrc、.gitconfig、.ssh全都在 Windows 用户目录下,和你 Windows 上的 git、VS Code、ssh 共享同一套配置,改一次两边都生效。代价是启动时会有一点点额外的路径解析开销,几乎感知不到。
4.2 Nerd Font 字体和 powerlevel10k,观感提升最大的一步
主题我推荐powerlevel10k,它的即时提示(instant prompt)机制对 MSYS2 这种 fork 慢的环境特别友好,配置好之后启动速度能有明显改善。安装:
git clone --depth=1 https://gitee.com/romkatv/powerlevel10k.git \ ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k然后在.zshrc里改:
ZSH_THEME="powerlevel10k/powerlevel10k"但光有主题没有字体,你会看到一堆方块和问号,这是新手最常卡住的地方。p10k 的图标依赖 Nerd Font 补丁字体,你需要去下载并安装一个,比如MesloLGS NF(p10k 官方推荐)或者CaskaydiaCove Nerd Font。下载.ttf文件后双击安装,或者右键“为所有用户安装”。
装完字体,回 Windows Terminal 的设置里把该 profile 的font.face改成对应字体名,注意名字要和系统里显示的完全一致,写错一个字符就没效果。这一步做完,重启终端,p10k 的配置向导会自动启动,问你喜欢什么风格,跟着选就行。选完会生成~/.p10k.zsh,以后想改再跑p10k configure。
如果你不想走交互式向导,也可以在.p10k.zsh里手动调,重点是这两个选项对 MSYS2 特别有用:
typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=true第一个让即时提示安静启动,不打印那一长串加载信息;第二个关掉 gitstatus 守护进程,改用内置的 git 检测。gitstatus 在 Linux 上性能很好,但在 MSYS2 下它会 fork 额外的进程,反而变慢,关掉之后大仓库里cd的响应速度改善非常明显。
4.3 三个必装插件和对应的配置片段
插件不用贪多,装三个覆盖 90% 场景就够了:zsh-autosuggestions(历史命令灰字提示)、zsh-syntax-highlighting(命令高亮,打错的命令标红)、zsh-completions(补全增强,前面已经用 pacman 装了)。
前两个走 git clone:
git clone --depth=1 https://gitee.com/mirrors/zsh-autosuggestions.git \ ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions git clone --depth=1 https://gitee.com/mirrors/zsh-syntax-highlighting.git \ ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting然后在.zshrc里启用:
plugins=(git zsh-autosuggestions zsh-syntax-highlighting)补全增强因为是通过 pacman 装的,不走 oh-my-zsh 插件机制,需要在.zshrc里单独处理:
fpath=(/usr/share/zsh/site-functions $fpath) autoload -Uz compinit && compinit -C-C参数的意思是跳过完整性检查,直接读补全缓存。补全缓存第一次生成会比较慢,之后就快了。这个参数在 MSYS2 上收益明显,因为完整性检查要挨个 stat 一堆文件,而 Windows 文件系统的 stat 开销比 Linux 大。
还有一点关于zsh-syntax-highlighting:它必须放在plugins数组的最后,因为它依赖前面所有插件定义的别名和函数,顺序错了高亮就会不准确。这个坑我第一次就踩过,明明装了却一点颜色都没有。
5. 路径、编码、互操作这三个坑,绕过去才算真会用
5.1 路径映射规则和 cygpath 的实战用法
MSYS2 的路径映射规则是:C:\Users\foo\bar对应/c/Users/foo/bar。注意 MSYS2 用/c,而老 Cygwin 用/cygdrive/c,这两个别搞混,网上的老帖子很多是 Cygwin 的写法,照抄会失败。
日常最实用的工具是cygpath,它专门做两种路径格式的互转:
cygpath -w /c/Users/foo # 输出 C:\Users\foo cygpath -u 'C:\Users\foo' # 输出 /c/Users/foo cygpath -m /usr/bin # 输出混合格式 C:/msys64/usr/bin什么时候用得上?最典型的是你要把一个路径传给 Windows 原生程序。比如你想用资源管理器打开当前目录,explorer .大多数时候能用,但路径带空格就会出问题,稳妥写法是explorer "$(cygpath -w "$PWD")"。又比如你写的脚本要生成给 Windows 程序读的配置文件,里面的路径必须用-w转成反斜杠格式。
反过来,路径里带空格的时候也不能偷懒。zsh 里for f in $(ls)这种写法在遇到带空格的文件名时会直接崩,正确姿势是用 glob:
for f in /c/Users/foo/Documents/*; do echo "$f" donezsh 的 glob 默认就处理好了空格和特殊字符,比ls输出靠谱得多。这是个通用原则,不只是 MSYS2 里要注意。
5.2 中文乱码的三种成因和对症处理
中文乱码这件事,原因可能出在三个不同的地方,得分开看。
第一种是 locale 没设对。检查一下locale命令的输出,如果LANG是空的或者显示POSIX,那中文显示和输入都会有问题。MSYS2 现在对 UTF-8 locale 支持已经不错了,可以在.zshrc里加:
export LANG=zh_CN.UTF-8 export LC_ALL=zh_CN.UTF-8如果报错说这个 locale 不存在,用locale -a | grep -i zh看看系统里到底有哪些,实在没有就用C.UTF-8,它对中文显示一样有效,只是排序规则不是中文习惯。
第二种是终端编码不对。Windows Terminal 默认就是 UTF-8,一般不用改;但如果你用的是老的控制台窗口(conhost),它的代码页可能是 936(GBK),那就必须切换。在 zsh 里执行chcp.com 65001可以临时切到 UTF-8,想永久生效就在.zshrc里加一行。
第三种是字体缺字。这种情况的表现是“能显示但缺笔画”或者“部分字变方块”,不是乱码而是缺字形。这时候换一个中文字形完整的字体就行,比如 Sarasa Term SC 或者更纱黑体家族的等宽版本,它们既带 Nerd Font 图标又有完整中文字形,一举两得。我现在用的就是这个方案,省得在字体之间反复切换。
5.3 和 Windows 原生工具混着用
MSYS2 最爽的地方就在于它能直接调用 Windows 的原生 exe。.exe后缀在 MSYS2 的 PATH 里是能被识别的,也就是说下面这些都能直接用:
code . # 直接开 VS Code winget list # 用 Windows 的包管理器 notepad.exe ~/.zshrc # 用记事本编辑配置 clip < somefile.txt # 把内容送进 Windows 剪贴板 powershell -Command "..." # 临时跑一段 PowerShell这里有个特别容易被忽略的工具:clip.exe是 Windows 自带的剪贴板写入工具,cat file | clip就能把内容复制到剪贴板,比装任何第三方工具都省事。反向的读取稍微麻烦点,可以用powershell -Command "Get-Clipboard"。
调用 Windows 程序时还有一个坑:参数里的路径会被自动转换。比如你跑some.exe /c/Users/foo,MSYS2 可能会把这个参数转成C:\Users\foo再传过去。大部分时候这是好事,但偶尔会坏事,比如某个参数看起来像路径但实际上不是。这时候可以用环境变量关掉转换:
MSYS2_ARG_CONV_EXCL="*" some.exe /not/a/path另外,用git的时候一定要配好换行符,否则文件在 Windows 和 Linux 之间来回跑会到处都是^M:
git config --global core.autocrlf input git config --global core.safecrlf warninput的意思是提交时把 CRLF 转成 LF、检出时不转,这样仓库里永远是干净的 LF,本地的文件保持原样。safecrlf warn会在不可逆转换时给个警告,避免你无意中搞坏二进制文件。
6. 常见问题速查与排查思路
6.1 安装与更新阶段的典型故障
这类问题占了新手遇到问题的一大半,基本都集中在 pacman 和网络这一层。我把最常出现的几种整理成表,遇到了直接对号入座。
| 现象 | 大概率原因 | 处理方式 |
|---|---|---|
pacman -Syu卡在某个包不动 | 官方源在国内速度差 | 换清华或中科大镜像源 |
PGP signature could not be verified | 本地密钥环过期 | 删/etc/pacman.d/gnupg后重新 init 和 populate |
failed to commit transaction (conflicting files) | 上次更新中断留下残骸 | pacman -S --overwrite '*' 包名强制覆盖 |
target not found: zsh | 数据库没同步 | 先pacman -Sy刷新数据库 |
| 提示要关闭终端 | pacman 自更新 | 关掉重开,再跑一次pacman -Su |
装完zsh命令找不到 | PATH 没初始化 | 用登录模式启动,检查/etc/zprofile |
关于镜像源还有一个经验:别只加一个源。清华和科大各加一行,一个挂了另一个还能兜底。虽然 pacman 是按顺序试,但实际用起来,双源比单源稳定得多,尤其是晚上高峰期。
6.2 显示与终端相关的排查
这类问题的表现通常很直观:颜色不对、图标是方块、中文糊成一团。排查顺序建议从上往下走。
第一步看字体。打开 Windows Terminal 设置,确认当前 profile 的font.face是不是你装的那个 Nerd Font,注意大小写和空格。装完字体后必须重启 Windows Terminal,它不会热加载字体,这一步经常被忘。
第二步看 TERM 变量。在 zsh 里echo $TERM,正常应该是xterm-256color。如果是dumb或者空,颜色和光标控制都会失效。可以在.zshrc里硬编码:
export TERM=xterm-256color第三步看颜色能力。跑一个简单的测试脚本,看 256 色是不是都能显示。如果只能显示 8 色,多半是 TERM 设成了xterm而不是xterm-256color。
还有一个更隐蔽的问题:某些主题+p10k 组合在浅色背景上对比度极低,看起来像“字消失了一样”。这不是 bug,是配色没调好。Windows Terminal 的colorScheme换成深色方案,或者在 p10k 配置里选一个对比度高的预设,问题就解决了。
6.3 性能与使用习惯上的几个心得
这部分是我用了一两年之后总结出来的,算是真正能提升体感的东西。
第一,别在/c/下做密集文件操作。MSYS2 访问/c/时走的是 Windows 的文件 API,虽然比 WSL 的 9p 快,但仍然比访问 MSYS2 自己的目录慢。如果你的项目需要频繁编译、大量小文件读写,把项目放在C:\msys64\home\你的用户名\下面速度会更好。日常编辑代码感知不明显,但跑构建脚本差别就出来了。
第二,慎用重量级的 oh-my-zsh 插件。git插件本身很轻,但它带的别名很多,补全时会去探测 git 仓库,在大仓库里按 Tab 会有明显延迟。如果某个仓库特别大,可以临时用git config --local关掉一些增强,或者干脆在.zshrc里按目录条件加载插件。
第三,善用 zsh 内建,少用外部命令。举个具体例子,取当前时间不要用date,用print -P '%D{%Y-%m-%d}';取文件不存在判断用[[ -f file ]]而不是ls。每减少一次 fork,在 MSYS2 上都是实打实的收益。这在写提示符和写脚本时尤其重要,提示符每次回车都要跑一遍,省下的时间会累积。
第四,定期清理补全缓存和 gitstatus 目录。.zcompdump文件过期会导致补全变慢甚至出错,删掉重新生成就行。gitstatus 关掉之后也记得把它的临时目录清一清,~/.cache/gitstatus下面有时候会积一堆东西。
第五,给重要的 dotfiles 建一个 git 仓库。这套配置调好之后,换机器要重新来一遍是很痛苦的。把.zshrc、.p10k.zsh、/etc/nsswitch.conf这些关键文件放进一个私有仓库,新机器上 clone 下来再建软链,十分钟就能恢复整套环境。
最后分享几点我自己的实际体会
这套配置我从最早用 Cygwin 折腾,到现在固定在 MSYS2 上跑了挺长时间,中间踩的坑基本都在上面了。我想额外强调两件事。
一个是不要追求和 Linux 完全一致。MSYS2 就是 MSYS2,它有自己的一套规则,硬要把它伪装成 Linux 只会引入更多问题。比如有人非要装apt、非要改uname的输出、非要把 systemd 那一套搬过来,最后只会把自己绕进去。正确的态度是:接受它的路径模型、用它自己的包管理、在需要 Windows 能力的时候大方地调用.exe,这样反而最省心。
另一个是配置要留在能复现的地方。我见过太多人调出一套漂亮的终端,结果重装系统后全没了,只能凭记忆再来一遍,而且往往记不全。dotfiles 这件事投入产出比极高,一次整理,长期受益。
如果你装完之后发现启动还是慢,先别急着换方案,跑一下zsh -x -i -c exit看看时间都花在哪一行了,八成是某个插件在偷跑命令。定位到之后再决定是换掉它还是加条件判断,比盲目换框架有效得多。这套东西调顺了之后,我在 Windows 上的终端操作效率,说实话和我在服务器上没太大差别了,除了极少数依赖内核的场景之外,日常写代码、跑脚本、连远程、整理文件,完全够用。