打开终端时为什么〜/ .bash_profile没有获取来源?

问题

我有一个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或者缺少这两个的配置文件会先在bashrc之前执行。
  2. 在这种情况下我的终端是非登录 shell吗?
  3. 如果是这样,为什么当在终端之后做su并输入密码时,为什么我没有执行配置文件,我也设置了上面提到的导出?

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

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

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

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

~/.bashrc中获取~/.bash_profile是错误的解决方案。 它应该是另一种方式; ~/.bash_profile应该来源~/.bashrc

请参阅DotFiles以获得更全面的解释,包括其原因的历史。

(另一方面,当通过apt安装openjdk时,应该通过包设置符号链接,这样你就不需要设置JAVA_HOME或更改PATH

您可以通过运行以下命令检查Bash shell是否作为login-shell启动:

 shopt login_shell 

如果答复已off您未运行登录shell。

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

摘自man bash

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

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

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

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

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

当您使用GUI时,shell通常永远不会作为登录shell运行,因此将所有内容放在~/.bashrc通常很好。

TL; DR

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

把你的东西放在~/.bashrc ,每次都会得到评估。

好的,我想明白,为什么这有意义?

了解正在发生的事情的关键点:

  • Linux上的所有进程都拥有并使用环境变量
  • 环境变量是inheritance的
  • 因此,在所有过程的父亲上设置它们足够了(特别是如果它需要一些计算时间。)
  • 登录设备后通常会启动所有进程的父亲(提供您的凭据)。
  • 当您登录计算机时,您可能只想做一次事情(例如检查新邮件……)。

所以“登录”时间通常是:

  • 在控制台模式下,当您登录(使用Ctrl-Alt F1)或通过ssh ,因为shell将是所有进程的父亲,它将加载~/.bash_profile
  • 在图形模式下,当您打开会话时,第一个进程(经典ubuntu的gnome-session )将负责读取
    .profile

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

它相当复杂, 完整的故事就在这里 。 但是对于ubuntu用户来说这是一个很常见的故障。 所以考虑到:

  • 你使用bash shell,
  • 你有一个~/.bash_profile并按照建议~/.bash_profile中添加~/.bashrc的加载,以便得到至少一个被评估的文件,无论调用机制是什么

这是一个快速建议放置东西的地方。

  • 〜/ .bashrc (如果你按照建议, 在任何场合都要进行评估

    用于快速评估环境变量和代码, 用于用户和仅限 bash的命令行用法(例如别名)。 欢迎使用。

    它会在以下情况下加载:

    • 在图形会话中创建一个新的shell窗口/窗格。
    • 打电话给bash
    • screen新窗格或选项卡。 (不是tmux !)
    • 图形控制台客户端( terminator / gnome-terminal …)中的任何bash实例,如果不勾选选项“run command as login shell”。

    由于先前的建议,它将在所有其他场合加载。

  • 〜/ .bash_profile仅在特定场合进行评估

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

    • 控制台登录(Ctrl-Alt F1),
    • ssh登录到这台机器,
    • tmux新窗格或窗口(默认设置),(不是screen !)
    • 明确调用bash -l
    • 只有勾选选项“run command as login shell”时,图形控制台客户端( terminator / gnome-terminal …)中的任何bash实例。
  • 〜/ .profile (仅在图形会话中获取)

    对于缓慢评估的环境变量,对于仅用户和所有图形会话进程都没有基础。 它在您的图形用户界面登录时加载。