Linux Zsh 环境配置
坑边闲话:Zsh 的配置笔者用了许多年,丰富的生态和现代化的配置,使得 Zsh 的体验非常良好。2023 年国庆之后,我把 Zsh 的配置用模块化的方式重新维护了一遍,更加贴合日常习惯。本文介绍我的 Zsh 配置文件,重点讲解总体架构和设计思路。
毫无疑问,Bash 依旧是 Linux shell 编程的首选。但是,Zsh 的强大生态和丰富插件却吸引了越来越多用户去使用。
Shell 是用户与 Linux 内核进行交互的重要中间件,Shell 一般通过 exec
系列命令生成新的进程执行 shell script,进而完成用户的意图。Shell 程序可以从命令行中获取参数、命令,也可以通过 stdin
(一般是文件)获取输入,两者在功能上是等价的。Zsh、Bash 等,均是 Shell 思想的具体实现,他们或许在某些语法上非常相似,但是彼此并不能互相完全兼容。比如 Zsh 中执行的 echo
命令,一般是内置的快速实现,而非 /bin/echo
,这些小差异带来了许多选择上的麻烦。
1. 配置的基本框架·
本章介绍配置 Zsh 环境的基本思路,学习本章将有助于读者理解笔者的代码框架。
在进行配置学习之前,先安装系统基础组件:
1 | sudo apt update |
随后笔者按照代码框架逐个介绍,节中将尽量少地给出代码。
1.1 识别系统类型·
可以使用 uname
、cat /etc/os-release
等方式查看系统类型,并将其设置为环境变量,方便后续操作。
1 | if [[ `uname -s` == "Linux" ]]; then |
1.2 设置合适的环境变量·
为了提高脚本的适用性,这里使用之前定义的 os_type
环境变量进行了分支跳转。优势有二:
- 将 NAS 路径保存为环境变量,在所有机器上保持同步,方便跳转并且可以提供一个统一界面;
- 将某些本地特殊路径保存为环境变量,方便跳转。
1.3 设置合适的别名·
通过 alias
命令为常用的组合设置别名,可以有效增加日常使用便捷性。
此处不推荐对较为大众化的命令进行别名覆盖,否则容易出现意想不到的问题。但是,alias ip=ip -color
这种无伤大雅的别名覆盖并不会存在太多隐患。
1.4 安装插件·
手动管理 Zsh 插件比较繁琐,使用 Zim 可以有效降低维护负担。使用 zmodule
命令可以激活本地 Zsh 扩展。
因为依赖因袭的 oh-my-zsh 插件,所以也要安装 oh-my-zsh,不导入只引用。
1 | zmodule ~/.local/share/oh-my-zsh/plugins/bundler |
Zim 项目本身提供了特别多的组建,通过 zmodule
命令可以迅速联机下载并安装。笔者使用了如下插件:
asciiship
: Zsh prompt,适用于 ASCII 模式。completion
: 自动补全。duration-info
: 为 Zsh prompts 提供上次命令执行所耗费时间的信息。environment
: 设置通用 Zsh 内置环境选项,比如历史记录文件、自动cd
目录等。eriner
: 笔者日常使用的主题,比较华而不实。git-info
: 将 git 存储库 status 信息提供给 Zsh prompt.git
: 提供了许多 git 子命令别名。input
: 为输入事件应用正确的绑定键。prompt-pwd
: 格式化当前工作目录以供 Zsh prompt 使用。termtitle
: 设置自定义终端标题。utility
: 为常用命令行程序添加别名和功能,比如为ls
、grep
和less
添加颜色等。
Zim 作为一个 Zsh 扩展管理,自然也支持第三方模块,笔者使用了如下第三方插件:
agkozak/zsh-z
: 快速跳转到最近访问过的目录。Aloxaf/fzf-tab
: 用fzf
替换 Zsh 默认的完成选择菜单。hlissner/zsh-autopair
: 在 zsh 中自动关闭并删除匹配的分隔符。pabloariasal/zfm
: Zsh 模糊标记。supercrabtree/k
: 使目录列表更具可读性,在文件和目录上添加一些颜色和一些 git 状态信息。unixorn/fzf-zsh-plugin
: 可让 fzf 搜索更多内容。zdharma-continuum/fast-syntax-highlighting
: 功能丰富的 Zsh 语法高亮。zsh-users/zsh-autosuggestions
: 类似 Fish 的 zsh 自动建议。zsh-users/zsh-completions
: 额外的 Zsh 的自动补全。zsh-users/zsh-history-substring-search
: 类似 Fish 的历史命令搜索。
1.5 设置键位绑定·
防止在 SSH 模式下键位实效。
1.6 配置 Conda 环境·
Conda 需要在启动环境之后立即激活。
1.7 配置 LaTeX 环境·
本模块有两个作用:
- 判断是否安装了 texlive,并导出符号
is_texlive_installed
,为组建更新模块提供值。 - 如果确实安装了,则启用环境。
可惜现在已经基本用不到了,Overleaf 一统天下。
1.8 设置系统更新模块·
由于系统上存在多个环境,如 Conda Python 环境、Apt 包环境等,所以有一个统一的系统更新命令是重要的。
- Apt/yum 包更新
- Conda 包更新
- LaTeX 包更新
使用统一的 os-update
命令即可更新全部系统可更新组件。
1.9 挂载与取消挂载·
主要是用来批量取消挂载 NFS 路径。
1.10 远程批量执行·
remote_update
是 remote-exe
的一种特殊调用。
1.11 第三方独立包管理·
笔者日常使用许多第三方软件,它们不在包管理器上游仓库提供,所以需要手动下载。pkg_manager
负责这些软件的自动下载安装。
执行 ltnt_install all
即可安装所有组件。
2. 自动补全模块·
Zsh 需要提供自动补全模板才可以使用补全功能,Python Click 有相应教程,自定义的函数也可以手动生成补全模板。
2.1 集成的简单补全模板·
本项目提供了对 K8S 组件和 ltnt_install
命令的补全模板,位于 completion 目录。
2.2 ZIM 补全模块·
可以在 ~/.local/share/zim/modules/zsh-completions/src
目录查看已安装的补全模板,也可以在该目录下按照 Zsh 规范创建自定义补全模板。
3. 全自动化配置指南·
最新的安装方式请参考项目主页。
3.1 自动部署·
首先,要保证家目录有 .zshenv
文件。编辑文件 vim ~/.zshenv
并配置 XDGDesktop 相关的环境变量。可通过如下命令完成:
1 | tee ${HOME}/.zshenv << EOF |
然后配置 Zsh:
1 | sudo chsh -s $(which zsh) |
输入 zsh
创建一个 Zsh 会话,系统会自动安装所有依赖。
随后执行下列命令安装所需的软件:
1 | ltnt_install all |
随后,创建一个 Tmux session,使用快捷键 prefix + I 安装额外插件。
3.2 重点讲解·
- 或许系统类型并导出为环境变量。因为 Zsh 脚本需要处理不同的操作系统,当然主要是 macOS 和 Linux,但是为了泛化脚本的可用性,这一步不可避免。
- 初始化一些环境变量。比如 TrueNAS 依赖
${HOME}/bin
里的脚本做存储管理。 - 设置别名。常见的命令,比如 iproute2 系列,有别名会更加方便。
- Zsh 插件的初始化。先安装 Oh-My-Zsh,然后初始化 Zim,随后初始化 Oh-My-Zsh. 这个顺序不能乱。该结果由实际测试得来,具体原因未知。
- 按键映射
conda
环境变量映射 (os-type
)latex
环境变量映射 (os-type
)os-update
函数定义 (os-type
)- Kubernetes 补全 (
os-type
)
总结·
本文以 Debian 12 为例,展示了如何配置 ~/.zshrc
,并提高自己日常使用 Linux 的效率。Linux 的高级境界就是给自己写脚本,比如:
- 写 Linux 脚本以简化系统级工作流程
- 写 VimScript / VimLua 脚本简化、加速文本编辑、程序调试速度
数字时代,开发能力才是决定性的技能。