当你打开终端或登录 Linux 系统时,Bash 会从一组启动文件中读取并执行命令。这些文件让你可以自定义 shell 环境:创建别名、向 $PATH 添加目录、设置环境变量以及更改 shell 提示符。
Bash 读取哪个启动文件取决于 shell 是登录 shell 还是非登录 shell。本指南解释了 .bashrc 和 .bash_profile 之间的区别、每个文件的加载时机,以及应将自定义设置放在何处。
交互式与非交互式 Shell
Shell 可以是交互式的,也可以是非交互式的:
- 交互式 shell - 从用户读取输入并将输出写入终端的 shell。这就是你在提示符下输入命令时使用的 shell。
- 非交互式 shell - 在没有用户交互的情况下运行的 shell,例如执行 Bash 脚本时。非交互式 shell 不读取
.bashrc或.bash_profile,但通过 SSH 运行命令时有一个例外,将在下面介绍。
登录与非登录 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 会读取并执行 ~/.bash_logout(如果存在)中的命令。这是放置清理命令的地方,例如清屏或删除临时文件。
当 Bash 作为交互式非登录 shell启动时,它会读取:
/etc/bash.bashrc- Debian 和 Ubuntu 上交互式 shell 的系统级设置。这些发行版对 Bash 进行了修补以读取此文件,这不是上游 Bash 的行为。Fedora 和 RHEL 使用/etc/bashrc,该文件由默认的~/.bashrc引用,而不是由 Bash 本身读取。~/.bashrc- 用户特定的 shell 设置。
下表总结了每种场景下读取哪些文件:
| Shell 类型 | 读取的文件 |
|---|---|
交互式登录(SSH、控制台、bash --login) | /etc/profile → ~/.bash_profile(或 ~/.bash_login 或 ~/.profile) |
交互式非登录(新终端选项卡、输入 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 引用它:
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi通过此设置,交互式登录和非登录 Bash 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 速查表。
| 文件 | 加载时机 | 用途 |
|---|---|---|
/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 中。如果你有意在 ~/.bashrc 中保留仅交互式的 PATH 更改,请确保 ~/.bash_profile 引用该文件,以便交互式登录 shell 也能获得此更改。
.bashrc 的更改未生效
编辑 ~/.bashrc 后,要么打开一个新终端,要么运行 source ~/.bashrc 以在当前 shell 中应用更改。
同时存在 .bash_profile 和 .profile 时只会使用其中一个
如果 ~/.bash_profile 存在,Bash 就会忽略 ~/.profile。要么将所有设置合并到一个文件中,要么让 ~/.bash_profile 引用 ~/.profile。
常见问题解答
我应该编辑哪个文件来添加别名?
将别名添加到 ~/.bashrc。只要 ~/.bash_profile 引用了 ~/.bashrc,你的别名就会在交互式登录和非登录 shell 中可用。
为什么我的终端不读取 .bash_profile?
大多数 Linux 终端模拟器(GNOME 终端、Konsole、xfce4-terminal)打开的是非登录 shell,它们读取的是 ~/.bashrc 而不是 ~/.bash_profile。只有 SSH 会话、控制台登录和 bash --login 才会触发登录 shell。
source 和 . 有什么区别?
它们是等效的。两者都在当前 shell 中执行文件中的命令。. ~/.bashrc 和 source ~/.bashrc 执行相同的操作。. 语法符合 POSIX 规范,而 source 是 Bash 的扩展。
当我执行脚本时,.bashrc 会运行吗?
对于本地脚本不会。脚本在非交互式 shell 中运行,除非脚本显式地引用 ~/.bashrc 或设置了 BASH_ENV 变量指向它,否则不会读取 ~/.bashrc。有一个例外:当 Bash 检测到其标准输入连接到网络连接时(例如 ssh user@host 'command'),即使 shell 不是交互式的,它也会读取 ~/.bashrc。Debian 和 Ubuntu 在默认的 ~/.bashrc 顶部放置了以下交互性检查:
# 如果不是交互式运行,则不执行任何操作
case $- in
*i*) ;;
*) return;;
esac我应该在哪里为 GUI 应用程序设置环境变量?
GUI 应用程序不会读取 .bashrc 或 .bash_profile。在基于 systemd 的系统上,将环境变量放在 ~/.config/environment.d/*.conf 中,或者在桌面环境设置中设置它们。