.bashrc 和 .bash_profile 的区别

cfi*_*her 512 bash bashrc .bash-profile

什么之间的区别.bashrc.bash_profile我应该使用哪一个?

Gil*_*il' 601

传统上,当您登录 Unix 系统时,系统会为您启动一个程序。该程序是一个外壳程序,即旨在启动其他程序的程序。它是一个命令行 shell:您可以通过键入另一个程序的名称来启动它。默认的 shell,一个 Bourne shell,从~/.profile它作为登录 shell 被调用时读取命令。

Bash 是一个类似 Bourne 的 shell。它从~/.bash_profile作为登录 shell 调用时读取命令,如果该文件不存在¹,它会尝试读取~/.profile

您可以随时直接调用 shell,例如通过在 GUI 环境中启动终端模拟器。如果 shell 不是登录 shell,则不会读取~/.profile. 当您将 bash 作为交互式 shell 启动时(即,不运行脚本),它会读取~/.bashrc(除非作为登录 shell 调用时,它只会读取~/.bash_profile~/.profile.

所以:

  • ~/.profile 是放置适用于整个会话的内容的地方,例如您希望在登录时启动的程序(但不是图形程序,它们进入不同的文件)和环境变量定义。

  • ~/.bashrc是放置仅适用于 bash 本身的内容的地方,例如别名和函数定义、shell 选项和提示设置。(您也可以将键绑定放在那里,但对于 bash,它们通常会进入~/.inputrc.)

  • ~/.bash_profile可以用来代替~/.profile,但它只能被 bash 读取,不能被任何其他 shell 读取。(如果您希望您的初始化文件在多台机器上工作并且您的登录 shell 不是对所有这些机器的 bash,这主要是一个问题。)~/.bashrc如果 shell 是交互式的,这是一个合乎逻辑的地方。我推荐以下内容~/.bash_profile

    if [ -r ~/.profile ]; then . ~/.profile; fi
    case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac
    
    Run Code Online (Sandbox Code Playgroud)

在现代 unices 上,还有一个与~/.profile. 如果您在图形环境中登录(即,如果您输入密码的程序在图形模式下运行),您不会自动获得读取~/.profile. 根据图形登录程序、随后运行的窗口管理器或桌面环境,以及您的发行版如何配置这些程序,您~/.profile可能会或可能不会被读取。如果不是,通常还有另一个地方可以定义环境变量和登录时要启动的程序,但遗憾的是没有标准位置。

请注意,您可能会在这里和那里看到建议将环境变量定义放入~/.bashrc或始终在终端中启动登录 shell。两者都是坏主意。这些想法中最常见的问题是,您的环境变量只会在通过终端启动的程序中设置,而不是在直接使用图标、菜单或键盘快捷键启动的程序中设置。

¹为完整起见,应请求:如果.bash_profile不存在,bash.bash_login在回退到.profile. 随意忘记它的存在。

  • +1 好帖子。也感谢您添加关于“登录图形与登录 shell”的部分......我有一个问题,我认为 ~/.profile 总是会为图形/shell 执行......但它不会在用户登录时执行通过图形登录。谢谢你解开了这个谜团。 (14认同)
  • @Gilles:您能否通过示例更详细地解释为什么在每个终端中运行登录 shell 是个坏主意?这只是桌面 Linux 的问题吗?(我认为在 OS X 终端上每次都会运行一个登录 shell,我从来没有注意到任何副作用(尽管我通常使用 iTerm)。但是我想不出很多我关心的环境变量之外的一个终端。(也许是 HTTP_PROXY?)) (4认同)
  • 语句 *`~/.bash_profile` 可以用来代替 `~/.profile`,但如果 shell 是交互式的,你还需要包含 `~/.bashrc`。* 误导,因为这些是正交问题。无论你是使用`~/.bash_profile` 还是`~/.profile`,如果你想让那里的设置在登录shell 中生效,你必须在你使用的那个中包含`~/.bashrc`。 (4认同)
  • @Gilles 当然可以,但是答案中句子的表述方式表明需要包含 `~/.bashrc` 与选择 `~/.bash_profile` 而不是 `~/.profile` 有关,这是不正确的. 如果有人在登录时获取的任何类型的脚本中包含`~/.bashrc`(这里是`~/.bash_profile` 或`~/.profile`)是因为他希望从`~/.bashrc` 设置为应用到登录 shell 的方式与它们应用于非登录 shell 的方式相同。 (3认同)
  • @Brandon 如果您在每个终端中运行登录 shell,这将覆盖环境提供的环境变量。在日常情况下,您可以逃避它,但是当您想在终端中设置不同的变量(例如,尝试不同版本的程序)时,它迟早会来咬您:运行login shell 将覆盖您的本地设置。 (2认同)
  • 将 OSX 终端更改为像其他一些 UNIX 发行版一样的交互式非登录 shell 是一项简单的任务。只需编辑 OSX 终端首选项,并将“Shells open with:”更改为命令“/usr/bin/login -f -l userid bash -i”。这将改变将所有终端启动为交互式非登录 shell 的约定。请记住,如果这样做,$HOME/.profile 将停止被获取。随后将对启动序列调用进行重大修改。 (2认同)
  • @PiotrDobrogost 好的,但是“.bash_login”只是“.bash_profile”的替代名称,几乎没有人使用。 (2认同)
  • 似乎很难让`~/.profile`同时兼容`csh`和`bash`,因为`csh`使用`setenv`,而`bash`使用`export`。 (2认同)

Jar*_*vin 59

从这篇短文

根据 bash 手册页, .bash_profile 为登录 shell 执行,而 .bashrc 为交互式非登录 shell 执行。

什么是登录或非登录 shell?

当您通过控制台登录(例如:输入用户名和密码)时,无论是在启动时物理地坐在机器上,还是通过 ssh 远程登录:在初始命令提示符之前执行 .bash_profile 以配置内容。

但是,如果您已经登录到您的机器并在 Gnome 或 KDE 中打开一个新的终端窗口 (xterm),那么 .bashrc 将在窗口命令提示符之前执行。当您通过在终端中键入 /bin/bash 来启动新的 bash 实例时,.bashrc 也会运行。

  • 轻微更新:“已执行”可能是一个有点误导性的术语,它们都有来源。执行听起来像是作为脚本运行,fork/exec yadda yadda。它在当前 shell 的上下文中运行。更重要的是,.bashrc 的运行频率更高。它在每次 bash 脚本运行时运行,如果您没有 .bash_profile 也是如此。此外,根据您设置 xterms 的方式,您可以创建一个来源 .bash_profile 的 shell (15认同)

Ric*_*lka 42

回到过去,当伪 tty 不是伪的,而且实际上是打字的,而且 UNIX 被调制解调器访问的速度非常慢,您可以看到每个字母都打印到屏幕上,因此效率是最重要的。为了在一定程度上提高效率,您有一个主登录窗口和您过去实际工作的任何其他窗口的概念。在您的主窗口中,您希望收到任何新邮件的通知,可能会在后台运行一些其他程序。

为了支持这一点,shells.profile专门针对“登录shells”获取了一个文件。一旦会话设置,这将做特别。Bash 将其扩展为在 .profile 之前先查看 .bash_profile,这样您就可以只将 bash 放在那里(这样它们就不会搞砸 Bourne shell 等,也查看 .profile)。其他 shell,非登录,只会获取 rc 文件,.bashrc(或 .kshrc 等)。

现在这有点不合时宜。您登录主 shell 的次数不像登录 gui 窗口管理器那样多。没有与任何其他窗口不同的主窗口。

我的建议 - 不要担心这种差异,它基于使用 unix 的旧风格。消除文件中的差异。.bash_profile 的全部内容应该是:

[ -f $HOME/.bashrc ] && . $HOME/.bashrc

并将您真正想要设置的所有内容放在 .bashrc 中

请记住,.bashrc 是为所有 shell、交互式和非交互式 shell 提供的。您可以通过将此代码放在 .bashrc 顶部附近来缩短非交互式 shell 的来源:

[[ $- != *i* ]] && return

  • 这是一个坏主意,请参阅 [我的回答](http://superuser.com/questions/183870/difference-between-bashrc-and-bash-profile/183980#183980)。特别是,您的环境变量只会在通过终端启动的程序中设置,而不是在通过图标、菜单或键盘快捷键直接启动的程序中设置。 (6认同)
  • @Gilles 我不明白你为什么这么说。使用如 Rich 所示的 `.$HOME/.bashrc`,`.bashrc` 中的设置将在登录 shell 中可用,因此也可以在桌面环境中使用。例如,在我的 Fedora 系统上,`gnome-session` 以 `-$SHELL -c gnome-session` 启动,因此读取了 `.profile`。 (6认同)
  • @Gilles re:“在 .profile 中包含 .bashrc”根本不是推荐的(实际上恰恰相反)。答案要么被编辑(看起来不是这样),要么你的评论与所说的不一致。 (3认同)
  • @PiotrDobrogost 哦,是的,Rich 的回答还有一个问题。在 `.profile` 中包含 `.bashrc` 通常是行不通的,因为 `.profile` 可能由 `/bin/sh` 而不是 bash 执行(例如,默认情况下在 Ubuntu 上用于图形登录),并且该 shell 可能不是交互式的(例如用于图形登录)。 (2认同)
  • 一般来说,+1,但我会添加到“短路......对于非交互式外壳”的建议(“在 .bashrc 顶部附近:`[[ $- != *i* ]] && return` "); 我确实喜欢我的一些 `.bashrc` 甚至对于非交互式 shell 也能执行,特别是在发出 `ssh hostname {command}` 时设置环境变量,以便正确执行远程命令(即使 shell 是非交互式)。但是稍后在`.bashrc` 中的其他设置应该被忽略。我通常检查 TERM=dumb 和/或未设置,然后尽早退出。 (2认同)

Fli*_*imm 22

看看ShreevatsaR这篇优秀的博客文章。这是一个摘录,但请转到博客文章,其中包括对“登录外壳”等术语的解释、流程图和 Zsh 的类似表格。

对于 Bash,它们的工作方式如下。阅读相应的列。执行 A,然后是 B,然后是 C 等等。B1、B2、B3 意味着它只执行找到的第一个文件。

+----------------+-----------+-----------+------+
|                |Interactive|Interactive|Script|
|                |login      |non-login  |      |
+----------------+-----------+-----------+------+
|/etc/profile    |   A       |           |      |
+----------------+-----------+-----------+------+
|/etc/bash.bashrc|           |    A      |      |
+----------------+-----------+-----------+------+
|~/.bashrc       |           |    B      |      |
+----------------+-----------+-----------+------+
|~/.bash_profile |   B1      |           |      |
+----------------+-----------+-----------+------+
|~/.bash_login   |   B2      |           |      |
+----------------+-----------+-----------+------+
|~/.profile      |   B3      |           |      |
+----------------+-----------+-----------+------+
|BASH_ENV        |           |           |  A   |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|~/.bash_logout  |    C      |           |      |
+----------------+-----------+-----------+------+
Run Code Online (Sandbox Code Playgroud)


Ell*_*iew 8

给 /ETC/profile 负责人的更好评论

在Flimm的上述巨大答案的基础上,我插在我的Debian的头这个新评论/etc/profile(你可能需要调整它为你的发行版。)

# For BASH: Read down the appropriate column. Executes A, then B, then C, etc.
# The B1, B2, B3 means it executes only the first of those files found.  (A)
# or (B2) means it is normally sourced by (read by and included in) the
# primary file, in this case A or B2.
#
# +---------------------------------+-------+-----+------------+
# |                                 | Interactive | non-Inter. |
# +---------------------------------+-------+-----+------------+
# |                                 | login |    non-login     |
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# |   ALL USERS:                    |       |     |            |
# +---------------------------------+-------+-----+------------+
# |BASH_ENV                         |       |     |     A      | not interactive or login
# |                                 |       |     |            |
# +---------------------------------+-------+-----+------------+
# |/etc/profile                     |   A   |     |            | set PATH & PS1, & call following:
# +---------------------------------+-------+-----+------------+
# |/etc/bash.bashrc                 |  (A)  |  A  |            | Better PS1 + command-not-found 
# +---------------------------------+-------+-----+------------+
# |/etc/profile.d/bash_completion.sh|  (A)  |     |            |
# +---------------------------------+-------+-----+------------+
# |/etc/profile.d/vte-2.91.sh       |  (A)  |     |            | Virt. Terminal Emulator
# |/etc/profile.d/vte.sh            |  (A)  |     |            |
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# |   A SPECIFIC USER:              |       |     |            |
# +---------------------------------+-------+-----+------------+
# |~/.bash_profile    (bash only)   |   B1  |     |            | (doesn't currently exist) 
# +---------------------------------+-------+-----+------------+
# |~/.bash_login      (bash only)   |   B2  |     |            | (didn't exist) **
# +---------------------------------+-------+-----+------------+
# |~/.profile         (all shells)  |   B3  |     |            | (doesn't currently exist)
# +---------------------------------+-------+-----+------------+
# |~/.bashrc          (bash only)   |  (B2) |  B  |            | colorizes bash: su=red, other_users=green
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# +---------------------------------+-------+-----+------------+
# |~/.bash_logout                   |    C  |     |            |
# +---------------------------------+-------+-----+------------+
#
# ** (sources !/.bashrc to colorize login, for when booting into non-gui)
Run Code Online (Sandbox Code Playgroud)

并在每个其他设置文件的开头添加此注释以引用它:

# TIP: SEE TABLE in /etc/profile of BASH SETUP FILES AND THEIR LOAD SEQUENCE
Run Code Online (Sandbox Code Playgroud)

值得注意的是,我认为 Debian 的/etc/profile默认来源 (includes) /etc/bash.bashrc,(即/etc/bash.bashrc存在时)。所以登录脚本读取这两个/etc文件,而非登录只读取 bash.bashrc。

另外值得注意的是,/etc/bash.bashrc当它不以交互方式运行时,它被设置为什么都不做。所以这两个文件只用于交互式脚本。


Mar*_*rcH 7

bash 本身的配置逻辑并不复杂,并在本页、serverfault 和许多博客的其他答案中进行了解释。然而,问题是Linux 发行版对 bash 的构成,我的意思是他们默认配置 bash 的复杂和各种方式。http://mywiki.wooledge.org/DotFiles简要提到了其中一些怪癖。这是 Fedora 29 上的一个示例跟踪,它显示了哪些文件来源哪些其他文件以及在一个非常简单的场景中的顺序:远程连接 ssh,然后启动另一个子 shell:

ssh fedora29
 ?? -bash # login shell
      ??? /etc/profile
      |    ?? /etc/profile.d/*.sh
      |    ?? /etc/profile.d/sh.local
      |    ?? /etc/bashrc
      ??? ~/.bash_profile
      |    ?? ~/.bashrc
      |          ?? /etc/bashrc
      |
      |
      ?? $ bash  # non-login shell
            ?? ~/.bashrc
                 ?? /etc/bashrc
                       ?? /etc/profile.d/*.sh
Run Code Online (Sandbox Code Playgroud)

Fedora 最复杂的逻辑在/etc/bashrc. 如上所示,/etc/bashrcbash 本身不知道一个文件,我的意思是不直接。Fedora 的/etc/bashrc测试是否:

  • 它是由登录 shell 获取的,
  • 它来自一个交互式 shell,
  • 它已经被采购

...然后根据这些做完全不同的事情。

如果您认为能记住上面的图表,那就太糟糕了,因为它还远远不够:该图表仅描述了一种情况,在运行非交互式脚本或启动图形会话时会发生略有不同的事情。我省略了~/.profile. 我省略了bash_completion脚本。出于向后兼容性的原因,调用 bash as/bin/sh而不是/bin/bash改变其行为。zsh 和其他 shell 呢?当然,不同的 Linux 发行版有不同的处理方式,例如Debian 和 Ubuntu 带有非标准版本的 bash,它具有特定于 Debian 的自定义。它特别寻找一个不寻常的文件:/etc/bash.bashrc. 即使您坚持使用单个 Linux 发行版,它也可能会随着时间的推移而发展。等等:我们甚至还没有接触过 macOS、FreeBSD…… 最后,让我们想想那些坚持他们的管理员配置他们必须使用的系统的更有创意的方式的用户。

正如关于这个主题的永无止境的讨论流所表明的那样,这是一个失败的原因。只要您只想添加新值,一些“反复试验”往往就足够了。当您想在一个(用户)文件中修改另一个(在 /etc 中)已定义的内容时,真正的乐趣就开始了。然后准备好花一些时间设计一个永远无法移植的解决方案。

为了最后一点乐趣,这里是截至 2019 年 6 月的 Clear Linux 上相同简单场景的“源图”:

ssh clearlinux
 ?? -bash # login shell
      ??? /usr/share/defaults/etc/profile
      |    ?? /usr/share/defaults/etc/profile.d/*
      |    ?? /etc/profile.d/*
      |    ?? /etc/profile
      ??? ~/.bash_profile
      |
      |
      ??  $ bash   # non-login shell
           ?? /usr/share/defaults/etc/bash.bashrc
           |      ?? /usr/share/defaults/etc/profile
           |      |    ?? /usr/share/defaults/etc/profile.d/*
           |      |    ?? /etc/profile.d/*
           |      |    ?? /etc/profile
           |      ?? /etc/profile
           ?? ~/.bashrc
Run Code Online (Sandbox Code Playgroud)