个人 Zsh 配置
适用场景:想要一套启动快、输入无延迟、补全体验现代的高性能 zsh 环境。你会学到 zinit 的 ice 延迟加载写法、插件选型对比(zsh-bench 实测),以及完整的 .zshrc / .zsh_aliases 参考配置。
由于系统、环境等差异可能过大,这里只是记录个人的 zsh 配置,仅供参考。
.zshrc
# My zsh settings with zinit
# ------------------- 核心配置 -------------------
# 性能优化选项
skip_global_compinit=1
DISABLE_MAGIC_FUNCTIONS=true
ZSH_DISABLE_COMPFIX=true
# 补全系统设置
COMPLETION_WAITING_DOTS="true"
ZSH_AUTOSUGGEST_MANUAL_REBIND=1
ZSH_AUTOSUGGEST_USE_ASYNC=1
ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=20
# ------------------- Powerlevel10k 即时提示 -------------------
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi
# ------------------- zinit 插件管理器 -------------------
source "/usr/share/zinit/zinit.zsh"
autoload -Uz _zinit
(( ${+_comps} )) && _comps[zinit]=_zinit
# zinit annexes
zinit ice wait"1" lucid as"null" for \
zdharma-continuum/zinit-annex-as-monitor \
zdharma-continuum/zinit-annex-bin-gem-node \
zdharma-continuum/zinit-annex-patch-dl \
zdharma-continuum/zinit-annex-rust
# ------------------- 主题 -------------------
zinit ice depth=1
zinit light romkatv/powerlevel10k
# ------------------- 核心插件 -------------------
# fzf
zinit ice from"gh-r" as"command"
zinit light junegunn/fzf
# 补全增强 & 补全初始化
zinit ice wait"0a" lucid atload"zicompinit; zicdreplay" blockf
zinit light zsh-users/zsh-completions
# fzf-tab
zinit ice wait"0b" lucid
zinit light Aloxaf/fzf-tab
# 自动建议
zinit ice wait"0c" lucid \
atload'
_zsh_autosuggest_start
bindkey "\`" autosuggest-accept
'
zinit light zsh-users/zsh-autosuggestions
# 历史命令
zinit ice wait"0d" lucid from"gh-r" as"program" \
bpick"*x86_64-unknown-linux-gnu.tar.gz" \
extract"" \
mv"atuin*/atuin -> atuin" \
atload'
eval "$(atuin init zsh)"
bindkey "^R" _atuin_search_widget
'
zinit light atuinsh/atuin
# 语法高亮
zinit ice wait"0e" lucid atinit"zpcompinit;zpcdreplay"
zinit light zdharma-continuum/fast-syntax-highlighting
# ------------------- CLI 工具 -------------------
# 核心工具(无延迟加载)
zinit ice wait"0" lucid from"gh-r" as"program" \
bpick"*x86_64-unknown-linux-musl.tar.gz" \
extract"" \
mv"eza* -> eza"
zinit light eza-community/eza
zinit ice wait"0" lucid from"gh-r" as"program" \
bpick"*x86_64-unknown-linux-gnu.tar.gz" \
extract"" \
mv"bat*/bat -> bat"
zinit light sharkdp/bat
# 延迟加载工具
zinit ice wait"1" lucid from"gh-r" as"program" \
bpick"*x86_64-unknown-linux-musl.tar.gz" \
extract"" \
mv"ripgrep*/rg -> rg"
zinit light BurntSushi/ripgrep
zinit ice wait"1" lucid from"gh-r" as"program" \
bpick"*x86_64-unknown-linux-gnu.tar.gz" \
extract"" \
mv"fd*/fd -> fd"
zinit light sharkdp/fd
zinit ice wait"1" lucid from"gh-r" as"program" \
bpick"*Linux_x86_64.tar.gz" \
extract""
zinit light jesseduffield/lazydocker
zinit ice wait"1" lucid from"gh-r" as"program" \
bpick"*linux-amd64.tar.gz" \
extract"" \
mv"fastfetch*/usr/bin/fastfetch -> fastfetch" \
atclone"chmod +x fastfetch" \
atpull"%atclone"
zinit light fastfetch-cli/fastfetch
zinit ice wait"1" lucid from"gh-r" as"program" \
bpick"*linux_x86_64.tar.gz" \
extract=""
zinit light muesli/duf
zinit ice wait"1" lucid as"program" pick"prettyping"
zinit load denilsonsa/prettyping
# bat-extras
zinit ice wait"1" lucid as"program" \
pick"src/batgrep.sh" pick"src/batdiff.sh" \
atload'alias batgrep="batgrep.sh"; alias batdiff="batdiff.sh"'
zinit light eth-p/bat-extras
# ------------------- 补全配置 -------------------
# 基础补全设置
zstyle ':completion:*' completer _expand _complete _ignored
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"
zstyle ':completion:*' menu no
# fzf-tab 基础设置
zstyle ':fzf-tab:*' use-fzf-default-opts yes
# fzf-tab 预览设置
zstyle ':fzf-tab:complete:cd:*' fzf-preview 'eza --icons -1 --color=always $realpath'
zstyle ':fzf-tab:complete:cd:*' popup-pad 30 0
zstyle ':fzf-tab:complete:__zoxide_z:*' fzf-preview 'eza --icons -1 --color=always $realpath'
zstyle ':fzf-tab:complete:z:*' fzf-preview 'eza --icons -1 --color=always $realpath'
# 进程补全预览
zstyle ':fzf-tab:complete:kill:argument-rest' fzf-preview 'ps --pid=$word -o cmd --no-headers -w -w'
zstyle ':fzf-tab:complete:kill:argument-rest' fzf-flags '--preview-window=down:3:wrap'
zstyle ':fzf-tab:complete:kill:*' popup-pad 0 3
# fzf-tab 快捷键
zstyle ':fzf-tab:*' fzf-bindings '`:accept'
zstyle ':fzf-tab:*' switch-group '<' '>'
# ------------------- 自动建议配置 -------------------
ZSH_AUTOSUGGEST_STRATEGY=(history completion)
ZSH_AUTOSUGGEST_COMPLETION_IGNORE='( |man |pikaur -S )*'
ZSH_AUTOSUGGEST_HISTORY_IGNORE='?(#c50,)'
# ------------------- fzf 配置 -------------------
export FZF_DEFAULT_OPTS="
--ansi
--layout=reverse
--info=inline
--height=50%
--multi
--cycle
--preview-window=right:50%
--preview-window=cycle
--prompt='λ -> '
--pointer='▷'
--marker='✓'
--color=bg+:236,gutter:-1,fg:-1,bg:-1,hl:-1,hl+:-1,prompt:-1,pointer:105,marker:-1,spinner:-1
"
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'
# ------------------- Conda 配置 -------------------
export CONDA_AUTO_ACTIVATE_BASE=false
conda() {
unfunction conda
eval "$(/opt/miniforge/bin/conda shell.zsh hook)"
conda $@
}
[[ "${CONDA_AUTO_ACTIVATE_BASE:-true}" == "true" ]] && {
eval "$(/opt/miniforge/bin/conda shell.zsh hook)"
conda activate base
}
# ------------------- 其他工具配置 -------------------
# zoxide
eval "$(zoxide init zsh --cmd cd)"
# 加载自定义别名
source $HOME/.zsh_aliases
# Powerlevel10k 配置
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
.zsh_aliases
alias l="eza --icons --long --header"
alias ls="eza --icons --grid"
alias ll="eza --icons --long --header"
alias la="eza --icons --long --header --all"
alias lg="eza --icons --long --header --all --git"
alias tree="eza --icons --tree -L1"
alias cat="bat"
alias man="tldr"
alias mkdir='mkdir -p'
alias df="duf -style unicode -hide-mp '/run/credentials/*'"
alias top="bpytop"
alias gedit="gnome-text-editor"
alias nvidia-smi="watch -n 3 -c nvidia-smi"
alias x="unar"
alias ff="fastfetch" # 快速显示fastfetch
function tmp() {
cd "$(mktemp -d /tmp/temp_XXX)" #创建临时目录
}
基本信息
- System:
Arch Linux x86_64 - Terminal:
kitty - Shell:
zsh - Theme:
powerlevel10k - Plugins Manerger:
zinit
原有配置痛点
- 如果历史命令中有中文,按
up键,会出现历史命令错位和终止终端的问题。 - 有些时候,命令输入延迟很高,已经输入完一段命令,但是终端是慢慢一个字一个字跳的。
- 性能还是不够高。
方案对比和选择
插件管理器或插件框架
| 序号 | 项目 | 说明 | 优势 | 劣势 |
|---|---|---|---|---|
| 1 | Oh My Zsh | 最流行的 Zsh 框架 | - 300+预置插件和 150+主题 - 配置简单直观 - 社区庞大 | - 启动速度慢 - 插件数量增加会显著降低性能 |
| 2 | Zinit | 现代化插件管理器 | - Turbo 模式启动速度提升 50-80% - 支持选择性禁用/启用功能 - 完整兼容 OMZ 和 Prezto 插件 | - 语法相对复杂 - 不适合新手 |
| 3 | Zim | 轻量级框架 | - 启动速度快 - 模块化设计 - 合理的默认配置 - 完整支持 OMZ 插件 | - 内置功能相对较少 |
| 4 | Sheldon | 可配置的插件管理器 | - 配置灵活 - 支持延迟加载 - 支持多种 shell | - 社区相对较小 |
| 5 | zsh4humans | 优化的 Zsh 环境 | - 启动速度快 - 默认配置合理 - 性能优化出色 | - 定制性相对较低 |
| 6 | Antigen | 传统插件管理器 | - 类似包管理器的使用方式 - 自动更新插件 | - 维护不够活跃 - 性能一般 |
| 7 | zgen | 轻量级管理器 | - 生成静态加载文件 - 启动相对较快 | - 功能相对简单 - 更新较少 |
| 8 | zplug | 全功能插件管理器 | - 功能丰富 - 并行安装插件 | - 已基本停止维护 - 性能一般 |
在这个里面,根据轻量化、性能好、社区维护活跃等因素,我最终选择了 Zinit 作为插件管理器。
插件
- 语法高亮:
fast-syntax-highlighting - 命令补全:
zsh-completions和fzf-tab - 智能建议:
zsh-autosuggestions - 目录跳转:
zoxide
| 序号 | 项目 | 说明 | 优势 | 劣势 |
|---|---|---|---|---|
| 1 | zoxide | Rust 编写的现代化目录跳转工具 | - 性能最快,启动速度快 - 使用简单直观 - 支持所有主流 shell | - 需要额外安装 - 不支持相对路径跳转 |
| 2 | autojump | Python 编写的经典跳转工具 | - 功能丰富完整 - 高级特性多 | - 学习曲线较陡 - 性能相对较慢 |
| 3 | z | Zsh 内置的目录跳转插件 | - 无需额外安装 - 与 Zsh 深度集成 | - 功能相对基础 - 仅支持 Zsh |
| 4 | z.lua | Lua 实现的跳转工具 | - 跨平台支持好 - 配置灵活 | - 性能比 zoxide 慢 - 需要 Lua 环境 |
| 5 | zsh-z | Zsh 专用的 z 实现 | - 轻量级 - 安装简单 | - 仅支持 Zsh - 功能较少 |
| 6 | ZLOcation | Shell 原生实现的跳转工具 | - 无外部依赖 - 性能稳定 | - 功能相对简单 - 社区较小 |
- 历史命令:
atuin
| 序号 | 项目 | 说明 | 优势 | 劣势 |
|---|---|---|---|---|
| 1 | atuin | 基于 SQLite 的现代化 shell 历史记录工具 | - 支持多设备同步 - 支持端到端加密 - 可按目录/主机等过滤搜索 - 记录命令执行时间和退出码 - 支持自托管同步服务器 - 配置简单,安装便捷 | - 首次打开仪表板较慢 - 在 mosh 下可能出现屏幕显示问题 - 同步机制不够直观 - 配置无法跨设备同步 |
| 2 | zsh-histdb | 基于 SQLite 的 Zsh 历史记录插件 | - 记录命令工作目录 - 记录命令执行主机 - 支持多数据库合并 - 与 zsh-autosuggestions 集成良好 - 支持按目录搜索历史 | - 不使用传统文本文件存储 - 项目维护不够活跃 - 仅支持 Zsh - 配置相对复杂 |
- 主题美化:
powerlevel10k
第三方命令行工具管理
由于该配置会同步 Docker深度学习环境、远程服务器使用,系统包管理器不同(有 ubuntu、archlinux、debian 等),故第三方命令行工具使用 zinit 管理,而非使用包管理器管理。则新建一系统时安装 zsh 和 zinit,再同步配置即可,其余的交给 zinit 管理。
TODO: 之后用
chezimo管理配置文件并同步到各个系统。
测试工具
这里使用 zsh-bench 基准工具来测试 zsh 交互性能,再进行对比。
测量指标
first_prompt_lag_ms(首次提示符延迟):打开新终端时,显示第一个命令提示符所需的时间- 良好: < 50ms
- 较差: > 100ms
first_command_lag_ms(首次命令延迟):输入第一个命令到执行完成的时间- 良好: < 200ms
- 较差: > 500ms
command_lag_ms(命令延迟):执行后续命令的平均响应时间- 良好: < 10ms
- 较差: > 50ms
input_lag_ms(输入延迟):按键到字符显示在屏幕上的时间- 良好: < 30ms
- 较差: > 50ms
exit_time_ms(退出时间):输入exit或按 Ctrl+D 到终端完全关闭的时间- 良好: < 100ms
- 较差: > 200ms
测试命令如下:
./zsh-bench -i 30 -l yes -g yes
测试结果
==> benchmarking login shell of user xiadengma ...
creates_tty=0
has_compsys=0
has_syntax_highlighting=0
has_autosuggestions=0
has_git_prompt=1
first_prompt_lag_ms=18.829
first_command_lag_ms=78.340
command_lag_ms=4.930
input_lag_ms=3.903
exit_time_ms=45.429
可以看到当前 zsh 配置在性能上表现良好,响应速度快。
验证与自查
- 新开终端
first_prompt_lag_ms应 < 50ms(用./zsh-bench -i 30 -l yes -g yes复测) - 输入历史命令中的中文后按
up键,不再错位或卡死终端 - 快速输入一段命令,字符不再逐个蹦出(
input_lag_ms无感) - 按
Ctrl+R打开 atuin 历史搜索,cd命令走 zoxide 跳转正常