为什么 ~/.bash_profile 在打开终端时没有得到来源?

Vir*_*ato 209 bash .profile environment-variables bashrc source

问题

我有一个 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
    
    Run Code Online (Sandbox Code Playgroud)
  3. 保存更改并退出

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

    echo $JAVA_HOME   (blank)
    echo $PATH        (displayed, but not the JAVA_HOME value)
    
    Run Code Online (Sandbox Code Playgroud)
  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
Run Code Online (Sandbox Code Playgroud)

问题

  1. 为什么我必须这样做?我认为 bash_profile、bash_login 或 profile 在没有这两个的情况下会在 bashrc 之前首先执行。
  2. 在这种情况下,我的终端是非登录shell 吗?
  3. 如果是这样,为什么在终端之后执行 su 并输入密码时,它没有执行我还设置了上述导出的配置文件?

gei*_*rha 265

~/.bash_profile仅在以登录模式启动时由 bash 提供。这通常是当你在控制台(登录Ctrl+ Alt+ F1.. F6),通过ssh,或者连接使用sudo -isu -运行作为另一个用户的命令。

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

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

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

采购~/.bash_profile~/.bashrc是错误的解决方案。它应该是相反的;~/.bash_profile应来源~/.bashrc

请参阅DotFiles以获得更详尽的解释,包括一些关于它为何如此的历史。

(附带说明,当通过 apt 安装 openjdk 时,符号链接应该由包设置,这样你就不需要设置JAVA_HOME或更改PATH

  • 我发现在 Ubuntu 12 中从侧边栏打开终端时,未加载 ~/.profile 文件。 (7认同)
  • 请记住,如果 .bash_profile 存在,则 bash 会忽略 .profile 。有关更多详细信息,请参阅我的回答 [here](http://superuser.com/a/570323/151431) 和 `man bash`。 (5认同)
  • @jcollum 很好。`.profile` 应该只在您登录时获取。 (4认同)
  • @terdon,是的,但是以图形方式登录时不涉及 bash,因此它直接用于`.profile`。 (3认同)
  • 哦,打开终端和登录不一样...我想登录_到终端_。 (2认同)

lga*_*rzo 55

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

shopt login_shell
Run Code Online (Sandbox Code Playgroud)

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

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

摘自man bash

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

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

  • 非常感谢 **shotp login_shell** 命令。惊人的!! (12认同)

小智 36

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

转到编辑 -> 配置文件首选项 -> 标题和命令选项卡检查“作为登录 shell 运行命令”选项

  • 启用此设置有哪些缺点? (2认同)
  • @chris 在很多情况下,您只是加载了比所需更多的代码。如果您的 ``~/.bash_profile`` 评估速度非常快,这可能无关紧要,可能就是这种情况。值得检查的一件好事是排除对其他通常成本很高的进程的任何调用。 (2认同)

Flo*_*sch 17

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

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


vaa*_*aab 9

TL; 博士

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

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

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

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

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

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

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

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

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

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

这是放置东西的快速建议。

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

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

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

    • 在图形会话中创建一个新的 shell 窗口/窗格。
    • 打电话 bash
    • screen新窗格或选项卡。(不是tmux!)
    • 图形控制台客户端 ( terminator/ gnome-terminal...)中的任何 bash 实例,如果您不勾选 选项“作为登录 shell 运行命令”。

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

  • ~/.bash_profile仅在特定场合评估

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

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

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