.bashrc和.bash_profile之间的区别


450

.bashrc.bash_profile和应该使用哪一个有什么区别?



如果您想也涉及到更完整的解释,请.profile查看以下问题:superuser.com/questions/789448/…–
Flimm

Answers:


518

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

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

您可以随时直接调用外壳程序,例如,通过在GUI环境中启动终端仿真器。如果该外壳不是登录外壳,则不会读取~/.profile。当您将bash作为交互式外壳程序启动时(即,不运行脚本),它将读取~/.bashrc(除非作为登录外壳程序调用,否则它仅读取~/.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

在现代的Uniice上,还有一个与之相关的复杂问题~/.profile。如果您在图形环境中登录(即,您输入密码的程序正在图形模式下运行),则不会自动获得显示为的登录外壳~/.profile。根据图形登录程序,之后运行的窗口管理器或桌面环境以及发行版配置这些程序的方式,~/.profile可能会或可能不会读取您的信息。如果不是这样,通常在另一个地方可以定义登录时要启动的环境变量和程序,但是很遗憾,这里没有标准位置。

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

¹ 为了完整起见,请提出要求:如果.bash_profile不存在,bash也会尝试.bash_login在退回到之前.profile。随时忘记它的存在。


11
为好帖子+1。还感谢您添加有关“登录图形与登录外壳”的部分...我有一个问题,我以为〜/ .profile总是会为图形/外壳执行...,但是当用户登录时它不会执行通过图形登录。谢谢您解决这个谜。
特雷弗·博伊德·史密斯

4
@Gilles:您能否通过示例更详细地说明为什么在每个终端中运行登录Shell是一个坏主意?这仅是台式机Linux的问题吗?(我收集到的信息是,每次在OS X Terminal上运行登录外壳程序时,我都没有注意到任何副作用(尽管我通常使用iTerm)。但是那时,我想不到很多我不在乎的环境变量一个终端(也许是HTTP_PROXY?)
iconoclast 2012年

2
@Brandon如果在每个终端中运行登录Shell,它将覆盖环境提供的环境变量。在日常情况下,您可以使用它,但是当您想在终端中设置不同的变量(例如,尝试使用不同版本的程序)时,它或早或晚会给您带来麻烦。登录外壳将覆盖您的本地设置。
Gilles 2012年

4
~/.bash_profile可以使用~/.profile~/.bashrc该语句代替,但如果外壳是交互式的,则还需要包含该语句误导,因为这些是正交的问题。无论您使用~/.bash_profile还是~/.profile必须包括~/.bashrc在其中,如果您希望从那里进行的设置都在登录外壳中生效。
Piotr Dobrogost

3
@Gilles可以,但是答案中句子的表达方式表明,包含的需要~/.bashrc与选择有关,~/.bash_profile而不是与~/.profile事实不符。如果有人~/.bashrc在登录时获取了源脚本中的任何一种(此处为~/.bash_profileor ~/.profile),那是因为他希望将来自的设置~/.bashrc应用于登录shell,就像他们将其应用于非登录shell一样。
Piotr Dobrogost 2013年

53

从这篇短文

根据bash的手册页,对于登录Shell执行.bash_profile,而对于交互式非登录Shell执行.bashrc。

什么是登录或非登录外壳?

当您通过控制台登录时(例如:键入用户名和密码),或者在引导时实际坐在计算机上,或者通过ssh远程登录:执行.bash_profile以配置初始命令提示符之前的内容。

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


12
轻微更新:“执行”可能是一个有点误导性的术语,它们都是来源。执行声音听起来像是作为脚本运行的,fork / exec yadda yadda。它在当前shell的上下文中运行。更重要的是,.bashrc的运行频率更高。它会在每次运行bash脚本时运行,也可以在没有.bash_profile的情况下运行。另外,根据您如何设置xterm,您可以创建一个外壳程序来获取.bash_profile的资源
Rich Homolka 2010年

36

在过去,当伪tty不是伪tty时,实际上,可以键入,并且UNIX被调制解调器访问如此之慢,以至于您可以看到每个字母都被打印到屏幕上,效率是最重要的。为了提高效率,您有一个主登录窗口以及您以前实际使用过的其他任何窗口的概念。在主窗口中,您希望收到任何新邮件的通知,也可能在后台运行其他程序。

为此,shell .profile专门在“ login shell”上提供了一个文件。一旦建立会话,这将做特别的事情。Bash对此进行了扩展,使其首先在.profile之前先查看.bash_profile,这样您就可以只在其中放置bash内容(这样它们就不会弄坏Bourne外壳,等等,它们也查看了.profile)。其他非登录外壳将仅提供rc文件.bashrc(或.kshrc等)的源代码。

现在有点过时了。登录到主shell的次数不及登录gui窗口管理器的次数。主窗口与其他窗口没有任何不同。

我的建议-不用担心这种差异,它基于使用UNIX的较旧样式。消除文件中的差异。.bash_profile的全部内容应为:

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

并将您实际要设置的所有内容都放在.bashrc中

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

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


6
这是一个坏主意,请参阅我的回答。特别是,您的环境变量将仅在通过终端启动的程序中设置,而不是在直接使用图标或菜单或键盘快捷键启动的程序中设置。
吉尔斯(Gilles)2010年

4
@吉尔斯,我不明白你为什么要这样。随着.$HOME/.bashrc为Rich以上表明,在设置.bashrc将在登录shell可用,因此桌面的良好环境。例如,在我的Fedora系统上,gnome-session启动为-$SHELL -c gnome-session,因此.profile被读取。
Mikel 2012年

2
@PiotrDobrogost哦,是的,Rich的答案还有另一个问题。包括.bashrc.profile通常不工作,因为.profile可以通过执行/bin/sh和不bash的(例如在Ubuntu用于通过缺省图形登录),且壳可以不是互动(例如,对于一个图形登录)。
吉尔斯2013年

3
@Gilles回复:根本不建议使用“ .profile中包括.bashrc”(实际上恰恰相反)。答案被编辑了(没有显示出来),或者您的评论与所讲的不一致。
迈克尔

2
总的来说,+ 1,但是我会建议增加“短路...非交互式外壳的短路”(“ .bashrc的顶部附近:[[ $- != *i* ]] && return”);我确实希望我的一些代码.bashrc即使对于非交互式shell也要执行,特别是在发出时设置env vars ssh hostname {command},以便可以正确执行远程命令(即使shell是非交互式的)。但是以后的其他设置.bashrc应该忽略。我通常检查TERM = dumb和/或未设置,然后提早纾困。
迈克尔

18

看看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      |           |      |
+----------------+-----------+-----------+------+

如果您可以根据提问者的特定需求定制答案,则最好不要在多个问题上发布相同的答案。如果两个问题的答案都完全相同,那么您应该发布一个答案并投票关闭其他问题,作为原始副本的副本。
Mokubai

1
@Mokubai另一个问题已经被标记为与此重复的问题。
Flimm

@ElipticalView:通过设置为不执行任何操作,您所指的行是:[ -z "$PS1" ] && return?我的答案中的表格给出了Bash运行的脚本列表,而不管脚本的内容如何,​​如果脚本本身具有line [ -z "$PS1" ] && return,那当然会生效,但是我认为这并不意味着我应该更改表。
Flimm

5

对/ 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)

此注释位于其他每个安装文件的开头,以供参考:

# TIP: SEE TABLE in /etc/profile of BASH SETUP FILES AND THEIR LOAD SEQUENCE

值得一提的是,我认为Debian的/ etc / profile默认情况下包含/etc/bash.bashrc(包括/etc/bash.bashrc)。因此,登录脚本读取两个/ etc文件,而非登录读取仅bash.bashrc。

还要注意的是/etc/bash.bashrc设置为在不交互式运行时不执行任何操作。因此,这两个文件仅用于交互式脚本。


4

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

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

  • 它是由登录外壳提供的,
  • 它是由一个交互式外壳提供的,
  • 它已经被采购

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

如果您认为可以记住上面的图,那就太糟糕了,因为它还不够用:该图仅描述了一种情况,在运行非交互式脚本或启动图形会话时,会发生稍微不同的事情。我已经省略了~/.profile。我省略了bash_completion脚本。出于向后兼容性的原因,请以bash身份调用/bin/sh而不是/bin/bash更改其行为。zsh和其他shell呢?当然,不同的Linux发行版的处理方式也有所不同,例如Debian和Ubuntu附带了非标准版本的bas h,它具有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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.