尝试 fish shell
注意:nvs 已被本文作者认为过时,且其不原生支持 fish,需要额外安装 bash 兼容层,会拖慢操作速度。推荐使用的是 fnm - Fast Node Manager,一个使用 Rust 编写的、兼容 bash / fish / zsh / PowerShell 的 node 版本管理工具,并且支持一键安装。详细请参考项目主页
从很久之前就开始观察到我使用的终端模拟器(iTerm2)新建 tab 时变得很慢,但一直没有仔细去调整。今天终于忍无可忍,想要搞清楚是怎么回事。
为什么我的 zsh 变慢了
如果你是跟我一样的初级选手,对 shell 脚本并无超出实用范围的兴趣,那你也很可能是直接用 oh-my-zsh 直接搞一套插件下来进行定制的……这种模式很常见也很高效,无可厚非。oh-my-zsh 有一些问题(或者也可能是 zsh 本身有一些问题),例如 .zcompdump
文件突然损坏导致没有办法使用自动补全功能。这导致我最开始以为是其中自带的某个插件导致 zsh 启动缓慢。
在 ~/.zshrc
头部和尾部分别加入以下内容来开启 profile:
|
|
然后运行 zsh
,即可查看各个模块启动时间的占比。
这里我没有截图,所以只能说结论:我的结果与 Little Thing #2 — Speeding up ZSH 作者的结果是类似的,问题出在 nvm 插件。更准确地说,是 nvm 的 default version 功能拖慢了 zsh 的启动速度。
nvm 是什么
nvm 是一个用于管理 node 版本,方便切换环境和进行多版本测试的第三方环境管理器。如果你有使用过 pyenv 或者 conda,很容易理解 nvm 就是他们的 node 专属版。在 nvm 中你可以指定一个安装的 node 版本为默认版本。例如我可以指定 node 12 为默认版本,然而在某一个项目(例如 ~/github/my_node_project
)中使用 node 14 版本;这样在这个项目之外的地方,直接运行 node
会启动 v12 的 node 交互终端。
从很久以前有一些用户就注意到 nvm 的这个功能会极大拖慢 shell 的启动速度,例如 #1277,#2084和#2251。但作者提出造成缓慢的原因在于 npm 运行本身就很慢,而他不接受除“在 npm 中进行修复”以外的其他方案。
弃用 nvm
最终我在 nvm 某个 issue 下一条被标记为 spam 的评论中发现了 nvs 这个管理器,作用与 nvm 类似,但是使用的是 link 模式,也就是通过软链接来设置默认 node 版本。这完全避免了在 shell 启动时去调用 npm。
|
|
安装完成之后,重新启动一个 zsh,然后使用 nvs add xxxx
来安装某个版本的 node。要将某版本的 node 设置为默认版本,使用 nvs link xxxx
。具体原理是:nvs 会创建软链接到 ~/.nvs/default/bin
中,而这个目录已被 nvs 加入 PATH
环境变量。
其实这篇文章到这里就该结束了,因为我的 zsh 启动慢的问题已经被解决。但之前一直有被人安利过 fish shell,于是就借机尝试下这个传说中很快的 shell。
fish shell
macOS 上安装相对简单,brew install fish
一句话搞定,但真正需要注意的是 fish 不兼容 bash 语法(简单撇了一眼主要应该是设置变量和脚本控制流的语法不一样)。这里简单记录下我常用的工具相关的配置。
设置,以及包管理器
fish 自带一个有 web 界面的配置工具 fish_config
,直接运行就会打开浏览器页面,配置完成后回到终端按下回车退出。这个工具不是很实用,基本只能挑选主题配色和 prompt,以及查下命令历史。
fish 的配置文件在 ~/.config/fish/config.fish
,默认是没有这个文件的,只有下文提到的内容需要这个文件。另外函数的定义在 ~/.config/fish/functions
,文件名与函数名一致。
fish 包管理器推荐的是不会拖慢启动速度的 fisher,安装请参考官方文档。
Bash 兼容层
有两个 bash 兼容层,可用于运行 bash 脚本并将环境保留到 fish 中:
这两个兼容层都可以使用 fisher
安装:fisher add edc/bass jorgebucaran/fish-bax
。
注意在运行多条命令时,两个程序似乎有所区别。
nvs 支持
nvs 需要使用到 bash 兼容层。将这个函数保存在配置目录的 functions
目录中,文件名与函数名相同,后缀为 .fish
。嫌麻烦的话直接 funced nvs
编辑完成按回车退出,然后 funcsave nvs
保存到文件。
|
|
因为 nvs 包含交互式操作,所以这里使用的是 bass
这个 bash 兼容层。
此外,还需要将 ~/.nvs/default/bin
目录加入 PATH 环境变量,方法在下一小节。
PATH 环境变量
fish 推荐使用 fish_user_paths
来管理自定义 PATH 变量,修改即时生效。
|
|
conda 支持
conda 支持 fish,但是需要在配置文件 ~/.config/fish/config.fish
中添加一些内容,运行 conda init fish
即可。要注意的是 conda 会覆盖 fish_right_prompt
函数,用于在右侧显示当前的 conda 环境名称。
命令耗时
对于可能运行比较久的命令,显示耗时信息是很有帮助的;但是用户通常不会记得手动加 time
。fish 在执行完一个命令后会触发 fish_postexec
事件,并且耗时信息会存储在 CMD_DURATION
变量中,因此可以使用事件函数来展示耗时信息。
|
|
注意这个函数的定义放在配置文件(~/.config/fish/config.fish
)中才可以正常工作。事件函数如果放在 functions
目录下,要在被手动调用后才会自动被事件触发。
GPG agent
macOS GPG Tools 用户需要在配置文件中加入这些内容才能正常使用 GPG agent 处理 ssh 请求。
|
|