
当你打开终端或登录 Linux 系统时,Bash 会读取并执行一组启动文件中的命令。这些文件让你可以定制自己的 shell 环境:创建别名、将目录加入 $PATH、设置环境变量,以及更改 shell 提示符。
Bash 会读取哪个启动文件,取决于当前 shell 是登录 shell 还是非登录 shell。本指南将解释 .bashrc 与 .bash_profile 的区别、每个文件在何时被加载,以及你的个性化配置应该放在哪里。
交互式与非交互式 Shell
shell 既可以是交互式,也可以是非交互式:
- 交互式 shell:从用户读取输入并将输出写到终端的 shell。你在提示符下输入命令时使用的就是它。
- 非交互式 shell:无需用户交互即可运行的 shell,例如执行 Bash 脚本时。非交互式 shell 不会读取
.bashrc或.bash_profile,但有一个例外——通过 SSH 执行的命令(见下文)。
登录 Shell 与非登录 Shell
交互式 shell 既可以是登录 shell,也可以是非登录 shell:
- 登录 shell:在登录系统时启动,包括通过 SSH 登录、在本地控制台登录,或使用
--login选项启动 Bash。 - 非登录 shell:在图形桌面中打开新终端窗口或标签页时启动,或在已有 shell 中输入
bash时启动。
你可以运行以下命令来检查当前 shell 是否为登录 shell:
shopt login_shell
如果输出为 login_shell on,则为登录 shell;如果输出为 login_shell off,则为非登录 shell。
启动文件加载顺序
当 Bash 以交互式登录 shell 启动时,会按以下顺序读取这些文件:
/etc/profile:系统级设置。该文件通常会引用/etc/profile.d/下的脚本。~/.bash_profile:用户级登录设置。如果该文件不存在,Bash 会依次查找~/.bash_login、再查找~/.profile,并执行找到的第一个文件中的命令。
当登录 shell 退出时,如果存在 ~/.bash_logout,Bash 会读取并执行其中的命令。清理命令(如清屏或删除临时文件)就放在这里。
当 Bash 以交互式非登录 shell 启动时,它会读取:
/etc/bash.bashrc:Debian 与 Ubuntu 上交互式 shell 的系统级设置。这些发行版对 Bash 做了补丁,使其读取该文件,这并非上游 Bash 的默认行为。Fedora 与 RHEL 改用/etc/bashrc,且它是由默认~/.bashrc引用的,而非由 Bash 自身读取。~/.bashrc:用户级 shell 设置。
下表汇总了每种场景下会读取哪些文件:
| Shell 类型 | 读取的文件 |
|---|---|
交互式登录 shell(SSH、控制台、bash --login) | /etc/profile → ~/.bash_profile(或 ~/.bash_login 或 ~/.profile) |
交互式非登录 shell(新终端标签页、输入 bash) | Debian/Ubuntu:/etc/bash.bashrc → ~/.bashrc;Fedora/RHEL:~/.bashrc → /etc/bashrc |
| 非交互式(脚本) | 无(除非设置了 BASH_ENV) |
通过 SSH 的非交互式(ssh host command) | ~/.bashrc |
.bashrc 与 .bash_profile 的区别
.bash_profile 在每次登录 shell 启动时执行。.bashrc 在交互式非登录 shell 以及由远程 shell 守护进程启动的部分非交互式 Bash 会话中执行。
在实践中,大多数用户都希望自己的交互式配置在登录与非登录的 Bash shell 中都能生效。标准做法是将这些配置放进 ~/.bashrc,然后让 ~/.bash_profile 去引用(source)它:
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
采用这种写法后,交互式的登录 shell 与非登录 shell 都会加载同一份配置。
配置该放在哪个文件
| 个性化配置 | 文件 | 原因 |
|---|---|---|
| 别名 | ~/.bashrc | 在每个交互式 shell 中可用 |
| Shell 函数 | ~/.bashrc | 在每个交互式 shell 中可用 |
提示符定制(PS1) | ~/.bashrc | 应用于每个新 shell |
$PATH 修改 | ~/.bash_profile 或 ~/.profile | 为登录会话设置,并被子进程继承 |
环境变量(export) | ~/.bash_profile 或 ~/.profile | 可供从登录会话启动的程序使用 |
| 登录时仅运行一次的命令 | ~/.bash_profile | 仅在登录时运行(如 ssh-agent、启动消息) |
.profile 与 .bash_profile 的区别
许多 Linux 发行版使用 ~/.profile 而不是 ~/.bash_profile。区别在于:
~/.bash_profile:仅由 Bash 读取。~/.profile:由 Bash 及其他 POSIX 兼容 shell(sh、dash)读取。
如果 ~/.bash_profile 和 ~/.profile 同时存在,Bash 只会读取 ~/.bash_profile 而忽略 ~/.profile。若希望 ~/.profile 也能被读取,可以删除 ~/.bash_profile,或在其中引用 ~/.profile。
Ubuntu 和 Debian 默认会创建 ~/.profile,而不会创建 ~/.bash_profile。Fedora 和 RHEL 则会创建 ~/.bash_profile。
macOS 注意事项
在 macOS 上,Terminal.app 与 iTerm2 默认打开的是登录 shell,这与大多数 Linux 终端模拟器相反。这意味着在 macOS 上,每次打开终端窗口都会读取 ~/.bash_profile(或 zsh 的 ~/.zprofile)。
自 macOS Catalina(2019)起,macOS 的默认 shell 是 zsh 而非 Bash。对应的 zsh 文件如下:
| Bash 文件 | Zsh 对应文件 |
|---|---|
~/.bash_profile | ~/.zprofile |
~/.bashrc | ~/.zshrc |
如果你的系统中这些启动文件尚不存在,你可以自行创建它们。
速查参考
如需可打印的速查表,请参阅 Bash 速查表(Bash cheatsheet)。
| 文件 | 加载时机 | 用途 |
|---|---|---|
/etc/profile | 登录 shell | 系统级环境设置 |
~/.bash_profile | 登录 shell | 用户登录设置,引用 .bashrc |
~/.profile | 登录 shell(若无 .bash_profile) | 可移植的用户登录设置 |
~/.bashrc | 交互式非登录 shell 及由远程 shell 守护进程启动的非交互式 Bash | 别名、函数、提示符,以及放在交互性判断之前的远程命令设置 |
/etc/bash.bashrc(Debian/Ubuntu)或 /etc/bashrc(Fedora/RHEL) | 非登录交互式 shell | 系统级 shell 设置 |
~/.bash_logout | 登录 shell 退出时 | 注销时运行的清理命令 |
故障排查
通过 SSH 连接时别名不生效——SSH 打开的是登录 shell,它读取 ~/.bash_profile 而不读取 ~/.bashrc。在 ~/.bash_profile 中加入 . ~/.bashrc,即可让别名在登录 shell 中也能加载。
远程 SSH 命令找不到程序——ssh user@host 打开的是交互式登录 shell,会读取 ~/.bash_profile。当用户登录 shell 为 Bash 时,运行 ssh user@host 'command' 会启动一个非交互式 shell,读取 ~/.bashrc。Debian 和 Ubuntu 的默认 ~/.bashrc 会在文件顶部的交互性判断处直接返回,而 Fedora/RHEL 的默认文件则会继续执行。如果远程命令在某台带该判断的机器上需要修改 PATH,应只把所需的 export 语句放在判断之前,将别名、提示符及其他交互式设置保留在判断之后。
.bashrc 中的 PATH 修改未生效——应将登录会话的 PATH 修改放在 ~/.bash_profile 或 ~/.profile 中。如果你有意将仅用于交互式环境的 PATH 修改保留在 ~/.bashrc,请务必让 ~/.bash_profile 引用该文件,使交互式登录 shell 也能获得它。
修改 .bashrc 后未生效——编辑 ~/.bashrc 后,要么打开一个新的终端,要么运行 source ~/.bashrc 在当前 shell 中使改动生效。
.bash_profile 与 .profile 都存在但只有一个被使用——如果存在 ~/.bash_profile,Bash 会忽略 ~/.profile。要么把设置合并到同一个文件,要么让 ~/.bash_profile 引用 ~/.profile。
常见问题(FAQ)
我应该编辑哪个文件来添加别名?将别名添加到 ~/.bashrc。只要 ~/.bash_profile 引用了 ~/.bashrc,你的别名在交互式登录与非登录 shell 中都会可用。
为什么我的终端不读取 .bash_profile?大多数 Linux 终端模拟器(GNOME Terminal、Konsole、xfce4-terminal)打开的是非登录 shell,会读取 ~/.bashrc 而非 ~/.bash_profile。只有 SSH 会话、控制台登录以及 bash --login 才会触发登录 shell。
source 与 . 有什么区别?两者等价。它们都在当前 shell 中执行文件里的命令。. ~/.bashrc 与 source ~/.bashrc 效果相同。. 语法符合 POSIX 标准,而 source 是 Bash 的扩展。
执行脚本时 .bashrc 会运行吗?本地脚本不会。脚本在非交互式 shell 中运行,不会读取 ~/.bashrc,除非脚本显式引用它,或者将 BASH_ENV 变量指向它。有一个例外:当 Bash 检测到标准输入连接到网络连接(如 ssh user@host 'command')时,即使 shell 并非交互式,它也会读取 ~/.bashrc。Debian 和 Ubuntu 在默认 ~/.bashrc 的顶部放置了如下交互性判断:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
我应该把 GUI 应用程序的环境变量放在哪里?GUI 应用程序不会读取 .bashrc 或 .bash_profile。在基于 systemd 的系统上,应将环境变量放在 ~/.config/environment.d/*.conf 中,或在你的桌面环境设置里配置。
总结
.bash_profile 由登录 shell 读取,而 .bashrc 由交互式非登录 shell 以及部分远程非交互式 Bash 会话读取。将交互式个性化配置放进 ~/.bashrc,在 ~/.bash_profile 中引用它,并将登录环境相关的设置保留在 ~/.bash_profile 或 ~/.profile 中。