我应该在哪里导出环境变量,以便 bash/dash、交互式/非交互式、登录/非登录的所有组合都能获取它?

我应该在哪里导出环境变量,以便 bash/dash、交互式/非交互式、登录/非登录的所有组合都能获取它?

提出这个问题的动机如下:

我使用的是 Ubuntu 12.04 LTS 2 和 Unity 桌面。在我的 .bashrc 文件中,我将几个目录附加到 PATH 变量并定义一些环境变量,例如 JAVA_HOME。当我从终端启动应用程序(运行 bash,我的默认 shell)时,这很有效,但对于使用 Unity 启动器的几个快捷方式,它们运行的​​应用程序似乎被定义为使用 #!/bin/sh(别名为 /bin/dash),并且它们不会获取 ~/.bashrc 或 ~/.profile 的内容。

我想我可以将所有这些快捷方式改为使用 /bin/bash 而不是 /bin/sh,以强制它获取 .bashrc 更改,但这似乎真的很不方便。

鉴于 Ubuntu 12.04(默认情况下)将 /bin/sh 别名为 /bin/dash,并且我的默认 shell 是 /bin/bash,是否有一个地方我可以选择修改 PATH 并定义环境变量,如果我希望它们存在于全部这些情况:

  1. 每当我创建一个非登录 bash shell(使用 unity 中的终端)
  2. 每当我创建一个登录 bash shell(例如,通过 ssh 远程登录)
  3. 每当我使用 Unity 应用程序启动器时(假设启动器使用 /bin/sh)。
  4. 每当 cron 作业执行时(假设 /etc/crontab 中的 SHELL=/bin/sh)。

如果我理解正确的话,我猜测:

  • (1)/(2)和(3)/(4)不同,因为(1)/(2)是 bash 而(3)/(4)是 dash。
  • (1) 和 (2) 不同,因为 bash 选择加载的文件根据它是否是登录 shell 而不同。
  • (3)和(4)不同,因为(3)会在某个时刻出现我已经登录(因此 ~/.profile 将由它的一个父进程获取,而(4)将在我登录时获取。不是登录,因此 ~/.profile 将不会被读取。

(如果其他因素也很重要,我不会感到惊讶,例如 shell 是否具有交互性,因此可能还有更多我甚至没有预料到的组合……在这种情况下,我很高兴我的问题得到“改进”。)

我希望在某个时候,有人必须制作某种指南,告诉您如何/在哪里以独立于 shell 的方式(或至少以 dash/bash 兼容的方式)修改环境变量......我只是似乎找不到正确的搜索词来找到这样的指南。

非常感谢解决方案或解决方案的指示!

更新:

  • 澄清:这是 12.04 安装过程中创建的默认 Ubuntu 用户,因此没什么特别的。它有一个 ~/.profile (明确来源 ~/.bashrc),并且唯一存在的 ~/.bash* 文件是 .bashrc、.bash_history 和 .bash_logout……所以没有 .bash_profile。
  • 强调范围:除了默认交互式 shell(bash)和碰巧使用 /bin/sh(别名为 dash)的任何脚本之外,我并不真正关心任何 shell,因此没有必要用任何东西来复杂化这一点额外的用于 tcsh/ksh/zsh/etc 的支持。

答案1

Shell 调用有点复杂。bash 和 dash 手册页中INVOCATION有关于此内容的部分。

总结来说(手册页中有更多详细信息,您应该阅读):

When bash is                   | it reads
-------------------------------|----------
login shell                    | /etc/profile and then the first of ~/.bash_profile, ~/.bash_login or ~/.profile that exists.
                               |
interactive non-login shell    | /etc/bash.bashrc then ~/.bashrc
                               |
non-interactive shell          | The contents of $BASH_ENV (if it exists)
                               |
interactive (as "sh")          | The contents of $ENV (if it exists)

-

When dash is                   | it reads
-------------------------------|---------
login shell                    | /etc/profile then .profile
                               |
interactive shell              | The contents of ENV (it it exists, can be set in .profile as well as in initial environment)

我不知道其他 shell 的情况,因为我从未使用过它们。最好的办法可能是设置几个环境变量来指向公共位置脚本,并在几种未涵盖的情况下手动获取该脚本(适当时)。

答案2

因此,有几种方法可以解决这个问题。许多人会选择以下方法:

a. 有一个文件,其中包含所有 sh 风格 shell 所共有的内容,例如.shcommon在每个等等中.profile .bashrc .kshrc,只需使用以下命令获取该文件. .shcommon

b. 将所有内容放入.profile并从其他文件中获取。

然后,可以在采购之前将特定 shell 或交互式和非交互式 shell 所需的内容放入相应的文件中.shcommon

就我个人而言,我不喜欢管理多个文件。因此,我使用以下方法:

首先,我需要的一切都进入了,.profile 因为我确实有一些 bash 和 ksh 特定的东西,所以我使用以下命令确定当前的 shell 名称:

# get name of current shell
# strip leading - from login shell
export SHELLNAME="${0#-}"

然后像下面这样为特定的 shell 输入命令(有些人更喜欢使用 case 语句)。

if [ "$SHELLNAME" = 'bash' ]
then
    shopt -s checkwinsize

elif [ "$SHELLNAME" = 'ksh' ]
then
    stty erase ^?
fi

如果我有只能在交互式 shell 中运行的命令,我会使用以下命令:

# check for interactive flag i in shell options $-
# in bash and ksh you could use the following, but breaks in dash
# if [[ $- == *i* ]]
if [ "$(echo $- | grep i)" != "" ]
then
  fortune
fi

例如,所有 sh 风格的 shell 中常见的内容PATH都可以放在顶部。

然后,我使用符号链接在所有 sh 样式的 shell 中加载同一个文件:

ln -s .profile .bashrc
ln -s .profile .kshrc

一些旁注,如果您有.bash_profile,那么 bash 将加载它而不是.profile但 dash 和 ksh 仍然会加载.profile 这可能是您问题的一部分。

此外,您可能需要考虑#!/bin/bash在脚本中使用而不是,除非#!/bin/dash您确实想要 POSIX 兼容脚本。bash 有很多非常好的额外功能,并且以 sh 形式调用 dash 或 bash 将禁用其中许多功能。

此外,bash 手册页很好地解释了.profileversus何时.bashrc加载。类似的规则也适用于 ksh。dash.profile在登录时加载,并允许您在交互式 shell 启动时加载使用ENV环境变量指定的文件.profile(也请查看 dash 手册页并搜索 .profile)。

答案3

由于情况 (1) 和 (2) 是通过在 .bashrc 和 .profile 中获取我的环境变量来解决的,因此真正的问题是“我为 (3) 和 (4) 获取这些相同变量的文件的名称是什么”。

看起来有askubuntu 上问题(如何获取要在 Unity 桌面中导入的环境变量)第 (3) 部分的答案。建议创建一个 ~/.xsessionrc 文件,该文件将由 /etc/X11/Xsession 提供。(我试过了,似乎有效……耶!)

我仍然对 (4) 做什么感到困惑。当然,如果创建一个 cron 作业(或守护进程),我可以用类似“bash -i -c /bin/foo”之类的命令替换“/bin/foo”,以强制它使用 bash 加载正确的环境变量,但这也意味着我必须修改可能代表我安装守护进程任务或 cron 作业的任何第三方工具。真恶心。

相关内容