深色模式
Shell startup 文件
概述
startup 文件最容易让人头大的地方,不是文件太多,而是文件名看起来都像亲戚:~/.bash_profile、~/.profile、~/.bashrc、~/.zprofile、~/.zshrc,改哪个都像有点道理。
这类问题如果只靠背文件名,很快就会乱。真正有用的顺序是先判断当前 shell 属于什么类型,再判断当前用的是 Bash 还是 Zsh,最后才决定配置该落到哪个文件。
先记住 startup 文件在解决什么问题
Shell 启动时,通常要做两类初始化:
- 准备环境变量,例如
PATH、JAVA_HOME、EDITOR - 准备交互能力,例如别名、函数、提示符、补全
这两类初始化不是一回事,所以 startup 文件也不会全都承担同一种职责。大体上可以先分成两类:
- profile 系列:偏登录环境
- rc 系列:偏交互体验
Zsh 里还多了一类更早执行的 zshenv,它的边界和前两类不完全一样,后面单独说。
先判断当前 shell 的类型
startup 文件读不读、读哪些,首先取决于 shell 的启动方式。
login shell
login shell 是“登录系统时拿到的 shell”。常见场景有:
- 通过 SSH 登录服务器
- 在 Linux 控制台登录
- 执行
bash --login - 执行
zsh -l
这类 shell 的重点是建立登录环境,所以通常会读取 profile 系列文件。
interactive shell
interactive shell 是“面向人直接操作的 shell”。常见场景有:
- 打开终端模拟器
- SSH 登录后进入命令行
- 在现有 shell 里再执行一次
bash或zsh
这类 shell 的重点是交互体验,所以通常会读取 rc 系列文件。
non-interactive shell
non-interactive shell 是“执行完命令或脚本就结束的 shell”。常见场景有:
bash script.shzsh script.zsh- CI/CD 的 shell 步骤
- 定时任务
这类 shell 一般不需要别名、提示符、补全,所以通常不会去读 rc 文件。
四种组合,先记这张表
login 和 interactive 是两个独立维度,组合起来大致是这样:
| 场景 | login | interactive |
|---|---|---|
| SSH 登录后进入终端 | 是 | 是 |
| 打开图形终端 | 否 | 是 |
bash --login script.sh | 是 | 否 |
bash script.sh | 否 | 否 |
先记住这三条判断线就够了:
- login 主要决定 profile 系列
- interactive 主要决定 rc 系列
- Zsh 的
~/.zshenv比较特殊,很多场景都会读
Bash 先抓两件事就够了
对于 Bash,真正最常打交道的通常就是两个文件:
~/.bash_profile~/.bashrc
别的文件不是没用,而是大多数日常配置绕不过这两个核心入口。
Bash 的主要文件怎么分工
/etc/profile
系统级 login 初始化文件。面向所有用户,通常由发行版或系统管理员维护。
~/.bash_profile
用户级 login 初始化文件。适合放用户自己的环境变量和登录时要做的准备。
如果这个文件存在,Bash 通常不会继续读 ~/.bash_login 或 ~/.profile。也就是说,这几个文件对 Bash 来说更像候补关系,不是一起全读。
~/.bash_login
用户级 login 初始化文件,优先级排在 ~/.bash_profile 之后。现在不算常见,但规则上仍然有效。
~/.profile
更通用的 POSIX 风格登录初始化文件。很多系统和工具会使用它,但对于已经明确使用 Bash 且有 ~/.bash_profile 的场景,它通常不再是主入口。
/etc/bashrc 或 /etc/bash.bashrc
系统级交互配置文件。文件名因系统而异,用途相近,主要面向所有 Bash 用户的交互能力。
~/.bashrc
用户级交互配置文件。别名、函数、提示符、补全之类的内容,通常都放这里。
~/.bash_logout
login shell 退出时执行的用户级收尾文件。知道它存在就够了,大多数人几乎不会天天改它。
Bash 的加载顺序怎么理解
最常见的三个场景,可以直接按这个判断:
SSH 登录或 bash --login
常见顺序是:
/etc/profile~/.bash_profile、~/.bash_login、~/.profile三选一- 如果用户在
~/.bash_profile里手动引入~/.bashrc,再继续读~/.bashrc
这里最容易误解的一点是:Bash 的 login shell 不会天然帮你自动读 ~/.bashrc。很多服务器上 SSH 登录后别名没生效,问题就出在这里。
打开终端模拟器,得到一个 non-login interactive Bash
常见顺序是系统级 rc 再到用户级 rc,也就是:
/etc/bashrc或/etc/bash.bashrc~/.bashrc
执行脚本
sh
bash script.sh这种场景通常不会按交互 shell 的方式去读 startup 文件。脚本跑偏时,先别假设 ~/.bashrc 一定参与了。
Bash 到底该把内容写到哪里
环境变量
像 PATH、JAVA_HOME、GOPATH、EDITOR 这类登录环境变量,优先放 ~/.bash_profile。
交互配置
像别名、函数、提示符、补全配置,优先放 ~/.bashrc。
常见写法
如果希望 login shell 也拥有 ~/.bashrc 里的交互配置,通常会在 ~/.bash_profile 里手动引入:
sh
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi这个写法很常见,也很合理。它的意思很直接:先建立登录环境,再把交互配置接进来。
Zsh 的分层比 Bash 更细
Zsh 和 Bash 最大的体验差异之一,就是文件分层更细。最值得先记住的是这三个:
~/.zshenv~/.zprofile~/.zshrc
只把这三个分清,已经能避开大多数坑。
Zsh 的主要文件怎么分工
/etc/zshenv
系统级最早执行文件。几乎任何 Zsh 启动时都会读到它。
~/.zshenv
用户级最早执行文件。它的特殊之处在于,很多非交互、非登录场景也会读到它。
这意味着一条很重要的规则:~/.zshenv 只适合放非常基础、不会产生副作用的内容。别名、提示符、输出语句这类东西,不该塞进去。
/etc/zprofile
系统级 login 初始化文件。
~/.zprofile
用户级 login 初始化文件。适合放用户自己的登录环境变量。
/etc/zshrc
系统级交互配置文件。
~/.zshrc
用户级交互配置文件。对 Zsh 用户来说,日常最常编辑的通常就是它。
/etc/zlogin 和 ~/.zlogin
login 流程末尾执行的文件,更适合放“登录完成后执行”的动作,而不是核心初始化逻辑。
/etc/zlogout 和 ~/.zlogout
logout 时执行的收尾文件。平时知道有这层即可。
Zsh 的加载顺序怎么理解
login + interactive
最常见的顺序是:
/etc/zshenv~/.zshenv/etc/zprofile~/.zprofile/etc/zshrc~/.zshrc/etc/zlogin~/.zlogin
non-login + interactive
最常见的顺序是:
/etc/zshenv~/.zshenv/etc/zshrc~/.zshrc
non-login + non-interactive
最容易被忽略的是这个场景。Zsh 在执行脚本时,通常至少还会读 zshenv 这一层。
这也是为什么 ~/.zshenv 写重了以后,脚本环境也会跟着被污染。
Zsh 到底该把内容写到哪里
环境变量
大多数用户自己的登录环境变量,优先放 ~/.zprofile。
交互配置
别名、函数、提示符、插件、补全,优先放 ~/.zshrc。
~/.zshenv 只放最基础内容
如果某个变量必须在所有 Zsh 进程中都存在,再考虑放到 ~/.zshenv。除此之外,宁可克制一点,也别把它写成第二个 ~/.zshrc。
Bash 和 Zsh 最容易混的点
Bash 重点看 ~/.bash_profile 和 ~/.bashrc
Bash 的主分工比较集中。大多数日常配置,围着这两个文件转就够了。
Zsh 多了 ~/.zshenv 这条早期入口
这条入口很有用,也很容易误伤脚本环境。Zsh 配置写乱时,很多问题就是从这里长出来的。
login shell 和 interactive shell 不是一回事
这是所有 startup 文件问题里最常见的根源。很多人以为“我打开的是终端,所以它肯定会读所有配置”。事实没这么慷慨。
一套够用的配置习惯
如果只是追求清楚、稳定,下面这套习惯已经够用了:
- Bash:环境变量放
~/.bash_profile,交互配置放~/.bashrc - Zsh:环境变量放
~/.zprofile,交互配置放~/.zshrc ~/.zshenv只放必须早加载、且不会污染脚本的内容- 公共别名和函数可以拆到独立文件,再由主配置文件引入
例如:
sh
. ~/.config/shell/aliases.sh
. ~/.config/shell/functions.sh这样做的好处不是显得整齐,而是后面排查配置时,脑子不会被一整个巨型 rc 文件拖进泥潭。
改完以后怎么立即生效
改完 ~/.bashrc 或 ~/.zshrc,最常见的做法是直接在当前 shell 里执行:
sh
source ~/.bashrc
source ~/.zshrc改的是 profile 文件时,也可以用同样方式重新加载,但前提是文件内容本身适合在当前 shell 里重读。更稳的做法通常还是重新开一个终端或重新登录一次。
