zsh

配置 zsh 作为日常使用的终端 shell

linux

linux 下配置 zsh 比较简单, 基本上都能用包管理器和 git 进行安装

安装 zsh

直接使用命令行就能安装 zsh

  • ubuntu:

    sudo apt install zsh
    
  • arch

    # 使用pacman
    sudo pacman -S zsh
    # 使用yay或者paru
    yay/paru -S zsh
    

配置 zsh 为当前用户默认 shell

查看当前 shell:

echo $SHELL
# 一般结果都是/bin/bash

设置 zsh 为当前用户默认 shell:

sudo chsh $USER
# 输入zsh的位置, 一般使用/bin/zsh

安装 oh-my-zsh

oh-my-zsh 官网提供两种方式进行简单安装

# 通过curl
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# 通过wget
sh -c "$(wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -)"

或者使用 github 镜像

# 使用curl
sh -c "$(curl -fsSL https://gh-proxy.com/https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# 使用wget
sh -c "$(wget -O- https://gh-proxy.com/https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

安装时会选择使用 omz 的.zshrc 替换原有的, 同时原来的.zshrc 会进行备份变成.zshrc.pre-oh-my-zsh

配置 zsh 插件

个人一般只用 zsh-syntax-highlighting 和 zsh-autosuggestions, 其他的就不做考虑

使用 git 将插件 clone 到本地 omz 插件目录

git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

或者使用 github 镜像

git clone https://gh-proxy.com/https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
git clone https://gh-proxy.com/https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

在.zshrc 中启用插件, 找到这一行

plugins=(git)

添加插件

plugins=(git zsh-autosuggestions zsh-syntax-highlighting)

重新 source 一下就行

source .zshrc

配置 powerlevel10k

本来之前用的是 omz 不加主题, 搭配 starship, 但是有点繁琐了, 所以就直接拿 powerlevel10k 来用了

同样使用 git 把主题 clone 到本地 omz 目录

git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k

或者使用 github 镜像

git clone --depth=1 https://gh-proxy.com/https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k

完成之后修改.zshrc

ZSH_THEME="powerlevel10k/powerlevel10k"

重新 source 一下.zshrc 就能看到 p10k 的引导界面, 根据引导进行设置即可

windows

window 之前用的 pwsh 加 starship, 也还行, 但是偶然想着能不能统一用 zsh

配置过程比 linux 要繁琐一点

安装 git

安装 git 没什么好说, 可以直接上官网下载

这里推荐找个国内镜像比如清华源, 在主页右边常用软件包安装程序中可以找到

唯一需要注意的是在安装时需要选择向 window terminal 添加 git-bash 的 profile

安装完成后把 git-bash 设置成默认 shell 的过程不多赘述

安装 zsh

git-bash 为 windows 提供了一个 bash 环境, zsh 需要额外安装

zsh 可以直接在 msys2 找到包

image

下载名为 zsh-$version$-x86_64.pkg.tar.zst 的包, 版本截至文章编写时为 5.9-4

两次解压后得到文件夹, 目录结构如下

|-- .BUILDINFO
|-- .INSTALL
|-- .MTREE
|-- .PKGINFO
|-- etc
|   `-- zsh
`-- usr
    |-- bin
    |-- lib
    `-- share

将整个文件夹覆盖到 git 安装目录, 再次打开 git-bash 即可调用 zsh

由于 git-bash 下没有 chsh 命令, 所以只能通过修改.zshrc 来让每次启动时自动切换到 zsh

在.bashrc 中加入如下内容(文件的末尾)

if [[ $- == *i* ]] && [ -t 1 ]; then
  exec zsh
fi

安装并配置 oh-my-zsh

omz 在 git-bash 的环境下安装方式相同, 参照上面 linux 的安装方法即可

解决 conda 和 mamba 的 hook 问题

在 windows 上使用 bash 或 zsh 这类 shell 时, 不可避免会遇到换行符的问题

如果按照上面的内容安装完了 zsh 之后使用 conda 和 mamba 进行 init, 会出现 ^M 也就是回车导致 zsh 解析失败, powerlevel10k 的 instant prompt 功能失效

问题定位

在使用 conda 和 mamba 进行 zsh 的 init 后, .zshrc 中会添加两段 hook, 启用 conda 和 mamba 的对应功能

每次打开 zsh 会报错

[WARNING]: Console output during zsh initialization detected.

When using Powerlevel10k with instant prompt, console output during zsh
initialization may indicate issues.

You can:

  - Recommended: Change ~/.zshrc so that it does not perform console I/O
    after the instant prompt preamble. See the link below for details.

    * You will not see this error message again.
    * Zsh will start quickly and prompt will update smoothly.

  - Suppress this warning either by running p10k configure or by manually
    defining the following parameter:

      typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet

    * You will not see this error message again.
    * Zsh will start quickly but prompt will jump down after initialization.

  - Disable instant prompt either by running p10k configure or by manually
    defining the following parameter:

      typeset -g POWERLEVEL9K_INSTANT_PROMPT=off

    * You will not see this error message again.
    * Zsh will start slowly.

  - Do nothing.

    * You will see this error message every time you start zsh.
    * Zsh will start quickly but prompt will jump down after initialization.

For details, see:
https://github.com/romkatv/powerlevel10k#instant-prompt

-- console output produced during zsh initialization follows --

omz 检测到了在 zsh 初始化时的输出, 在报错信息后紧接着两行

(eval):7: parse error near `^M'
(eval):15: parse error near `^M'

也就是脚本中包含了 windows 的回车, conda 和 mamba 的 init 过程失败, 导致 zsh 无法解析从而产生输出, 影响了 powerlevel10k 的 instant prompt 功能

回看.zshrc, 其中确实包含了两行 eval

# conda
eval "$('/d/miniforge3/Scripts/conda.exe' 'shell.zsh' 'hook')"
# mamba
eval "$("$MAMBA_EXE" shell hook --shell zsh --root-prefix "$MAMBA_ROOT_PREFIX")"

具体内容是 conda 和 mamba 各自调用了自己的 hook, 生成了自己的临时 hook 脚本, 交由 eval 来执行

但由于 conda 和 mamba 属于 windows 程序, 生成 hook 脚本过程中添加的换行符全部都为 windows 换行

eval 在执行 hook 脚本时无法解析其中的回车符(^M)从而发生了错误

上面的内容可以通过下面的方法来验证

# 手动执行命令生成hook脚本
'/d/miniforge3/Scripts/conda.exe' 'shell.zsh' 'hook' > conda_hook.txt
# 使用cat显示所有特殊字符
cat -A conda_hook.txt

回显中会包含大量 ^M

临时解决方案是在对应的命令结尾加上管道符将生成的 hook 脚本交由 dos2unix 来处理

使用 dos2unix 替换原来的 windows 换行为 unix 换行, 再交由 eval 来执行

# conda
eval "$('/d/miniforge3/Scripts/conda.exe' 'shell.zsh' 'hook' | dos2unix)"
# mamba
eval "$("$MAMBA_EXE" shell hook --shell zsh --root-prefix "$MAMBA_ROOT_PREFIX" | dos2unix)"

但是, 替换后仍然发生报错

(eval):unset:1: _CE_M^M: invalid parameter name

发现竟然还有 ^M?

于是对生成的 hook 脚本进行检查, 发现在 conda 的 hook 脚本中包含一个 eval

__conda_activate() {
    if [ -n "${CONDA_PS1_BACKUP:+x}" ]; then
        # Handle transition from shell activated with conda <= 4.3 to a subsequent activation
        # after conda updated to >= 4.4. See issue #6173.
        PS1="$CONDA_PS1_BACKUP"
        \unset CONDA_PS1_BACKUP
    fi
    \local ask_conda
    # 这里生成命令
    ask_conda="$(PS1="${PS1:-}" __conda_exe shell.posix "$@")" || \return
    # 这里eval执行
    \eval "$ask_conda"
    __conda_hashr
}

也就是说在 hook 脚本中又生成了一条临时命令交由 eval 来执行, 毫无疑问这里生成的内容包含 ^M

于是对 conda 的 hook 命令再做修改, 使用正则将 hook 脚本中对应的内容进行修改, 也就是加上 dos2unix

eval "$('/d/miniforge3/Scripts/conda.exe' 'shell.zsh' 'hook' \
  | sed 's#__conda_exe shell\.posix "\$@"#__conda_exe shell.posix "$@" | dos2unix#' \
  | dos2unix)"

原以为万事大吉, 结果依旧报错, 这回是 python

    Traceback (most recent call last):
      File "D:\miniforge3\Lib\site-packages\conda\exception_handler.py", line 28, in __call__
        return func(*args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^
      File "D:\miniforge3\Lib\site-packages\conda\cli\main.py", line 87, in main_sourced
        print(activator.execute(), end="")
    UnicodeEncodeError: 'gbk' codec can't encode character '\uf253' in position 937: illegal multibyte sequence

python 在执行 hook 时无法解析'uf253'(默认使用 gbk)

所以这里直接在.zshrc 环境变量添加一条

export PYTHONIOENCODING=utf-8

问题解决

最终方案

将 conda 和 mamba 的 hook 命令进行替换

# conda
eval "$('/d/miniforge3/Scripts/conda.exe' 'shell.zsh' 'hook')"

# conda(patch)
eval "$('/d/miniforge3/Scripts/conda.exe' 'shell.zsh' 'hook' \
  | sed 's#__conda_exe shell\.posix "\$@"#__conda_exe shell.posix "$@" | dos2unix#' \
  | dos2unix)"

# mamba
eval "$("$MAMBA_EXE" shell hook --shell zsh --root-prefix "$MAMBA_ROOT_PREFIX")"
# mamba(patch)
eval "$("$MAMBA_EXE" shell hook --shell zsh --root-prefix "$MAMBA_ROOT_PREFIX" | dos2unix)"

并添加一条环境变量(在.zshrc 的对应位置, conda 和 mamba 的 hook 执行之前)

export PYTHONIOENCODING=utf-8
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    960 引用 • 946 回帖 • 1 关注
6 操作
earph0n3 在 2025-09-03 15:09:59 更新了该帖
earph0n3 在 2025-09-03 15:07:16 更新了该帖
earph0n3 在 2025-09-03 15:06:30 更新了该帖
earph0n3 在 2025-09-03 14:02:26 更新了该帖 earph0n3 在 2025-09-03 13:16:44 更新了该帖 earph0n3 在 2025-09-03 13:14:35 更新了该帖

相关帖子

2 回帖
zsh

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...