为什么打开终端时无法获取〜/ .bash_profile?


175

问题

我有一个Ubuntu 11.04虚拟机,我想设置自己的Java开发环境。我做了如下

  1. sudo apt-get install openjdk-6-jdk
  2. 〜/ .bash_profile中添加了以下条目

    export JAVA_HOME=/usr/lib/jvm/java-6-openjdk
    
    export PATH=$PATH:$JAVA_HOME/bin
    
  3. 保存更改并退出

  4. 再次打开终端并输入以下内容

    echo $JAVA_HOME   (blank)
    echo $PATH        (displayed, but not the JAVA_HOME value)
    
  5. 什么也没发生,就像从未执行过JAVA_HOME的导出及其对PATH的添加一样。

我不得不转到〜/ .bashrc并将以下条目添加到文件末尾

#Source bash_profile to set JAVA_HOME and add it to the PATH because for some reason is not being picked up
. ~/.bash_profile

问题

  1. 为什么我必须这样做?我认为bash_profile,bash_login或profile在缺少这两个文件之前先在bashrc之前执行。
  2. 在这种情况下,我的终端是否为非登录外壳?
  3. 如果是这样,为什么在终端之后执行su并输入密码时,为什么我执行了上述导出操作的地方没有执行配置文件?

Answers:


223

~/.bash_profile在交互登录模式下启动时,仅由bash提供。通常只有在您通过控制台(Ctrl+ Alt+ F1.. F6)登录或通过ssh连接时才这样。

当您以图形方式登录时,~/.profile将由启动gnome-session的脚本(或您正在使用的任何桌面环境)专门提供源。因此~/.bash_profile,当您以图形方式登录时,根本就没有来源。

当您打开终端时,终端会以(非登录)交互方式启动bash,这意味着它将启动~/.bashrc

放置这些环境变量的正确位置是~/.profile,并且在您下次登录时效果应该很明显。

~/.bash_profile从中采购~/.bashrc是错误的解决方案。应该是相反的。~/.bash_profile应该出处~/.bashrc

有关更详尽的解释,请参见DotFiles,包括其历史原因的一些历史记录。

(顺便提一下,通过apt安装openjdk时,应通过软件包设置符号链接,这样就不必设置JAVA_HOME或更改了PATH


6
我发现从Ubuntu 12的侧栏中打开终端时,不会加载〜/ .profile文件。
jcollum

3
@jcollum很好。.profile当您登录时应该只采购。
geirha

2
哦,打开终端机与登录不一样...我当时想登录到终端机
jcollum

2
请记住,.profile如果.bash_profile存在,bash会忽略它。在这里 以及man bash更多详细信息中查看我的答案。
terdon

3
@terdon,是的,但是以图形方式登录时不涉及bash,因此它直接用于.profile
盖尔哈2014年

48

您可以通过运行以下命令检查Bash Shell是否作为登录Shell启动:

shopt login_shell

如果答复是off您没有运行登录shell。

阅读Bash手册的调用部分,了解Bash如何读取(或不读取)不同的配置文件。

摘录自man bash

当bash作为交互式登录shell或带有--login 选项的非交互式shell被调用时,它首先从文件中读取并执行命令/etc/profile(如果该文件存在)。读取文件后,它会寻找 ~/.bash_profile~/.bash_login~/.profile,按照这个顺序读取并执行从存在并且可读的第一个命令。

su另一方面,默认情况下也不会启动登录Shell,您必须使用--login选项告诉它这样做。


9
非常感谢shotp login_shell命令。太棒了!!
Viriato 2012年

27

我认为值得一提的是,您可以通过编辑配置文件首选项来更改gnome-terminal的默认值,以使用登录外壳程序(即bash -l)。

转到“编辑”->“配置文件首选项”->“标题和命令”选项卡,选中“将命令作为登录外壳运行”选项


1
启用此设置的不利之处是什么?
chris17年

2
@chris在很多情况下,您正在加载的代码多于所需的代码。您~/.bash_profile是否真的可以快速评估,这可能并不重要。要检查的一件好事是赶走通常很昂贵的对其他进程的所有调用。
Vaab

14

如果打开终端或运行su该外壳程序,则该外壳程序不作为登录外壳程序执行,而是作为普通的交互式外壳程序执行。因此它读取~/.bashrc但不是~/.bash_profile。您可以su使用该-l选项运行,以使其作为登录外壳程序运行您的外壳程序。

当您使用GUI时,该外壳程序通常永远不会作为登录外壳程序运行,因此最好将所有内容放入其中~/.bashrc


1
那就是我所做的并且有效的方法,但是请检查底部的人说的话,他建议将其放入bashrc并将其放在个人资料中是一个坏主意。....两种方法都可以,非常感谢。
Viriato 2012年

4

TL; DR

在经典推荐的ubuntu设置中,~/.bash_profile仅在特定情况下进行评估。这是有道理的。

将您的资料放入~/.bashrc,它会随时得到评估。

好的,我想了解一下,为什么这有意义?

了解发生了什么的关键点:

  • linux上的所有进程都具有并使用环境变量
  • 环境变量是继承的
  • 因此,只需将它们设置您所有进程的父进程上就足够了(尤其是在需要一些计算时间的情况下)。
  • 通常,在您登录设备后(提供凭据)启动所有流程之父 。
  • 在您登录计算机时,有些事情您可能只想做一次(例如,检查新邮件...)。

因此,“登录”时间通常为:

  • 在控制台模式下,当您登录(使用Ctrl-Alt F1键)或通过登录时ssh,由于外壳程序将成为所有进程的父进程,因此它将加载您的 ~/.bash_profile
  • 在图形模式下,当您打开会话时,将阅读第一个过程(gnome-session对于经典ubuntu)
    .profile

好吧,那我的东西放在哪里?

这很复杂,完整的故事在这里。但是这对于Ubuntu用户来说是很普遍的。因此考虑到:

  • 你用bash
  • 您有一个,~/.bash_profile然后按照建议~/.bashrc在您的文件中添加,~/.bash_profile以便至少获取一个可以评估调用机制的文件

这是放置物品的快速建议。

  • 〜/ .bashrc在所有情况下都将得到评估,只要您遵循建议)

    对于快速评估环境变量和代码为您的 用户只唯一的bash-命令行使用(别名为实例)。欢迎bashism

    它会在以下情况下自行加载:

    • 在图形会话中创建新的外壳窗口/窗格。
    • 呼唤 bash
    • screen新窗格或标签。(不是tmux!)
    • 如果您不勾选 “以登录外壳运行命令”选项,则图形控制台客户端(terminator/ gnome-terminal...)中的任何bash实例。

    由于先前的建议,它将在所有其他情况下加载。

  • 〜/ .bash_profile仅在特定情况下进行评估

    对于仅用户控制台会话进程的环境评估环境变量和代码。 欢迎bashism。它被加载到:

    • 控制台登录(Ctrl-Alt F1),
    • ssh登录到这台机器,
    • tmux新窗格或窗口(默认设置),(不是screen!)
    • 的显式调用bash -l
    • 仅当您勾选“以登录外壳运行命令”选项时,图形控制台客户端(terminator/ gnome-terminal...)中的任何bash实例。
  • 〜/ .profile (仅在图形会话中得到评估)

    对于慢评估的环境变量,并没有bashism,只有用户和所有的图形会话过程。登录后将其加载到图形用户界面中。


在bash确实加载配置文件的情况下,.profile如果.bash_profile不存在,它将加载。
大师

非常感谢您的明确解释。它可以帮助像我这样的新手。在Mac Mojave中,如果我将变量放在〜/ .bashrc中并执行源代码,然后如果我这样env做,则看不到env变量设置(我尝试关闭iTerm并重新打开)。但是我注意到,当我安装Android Studio和其他应用程序时,所有这些env var都设置在中/.bash_profile。所以当我添加/.bash_profile它时就像魅力一样。这是为什么?
sofs1
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.