子shell不会获取空的环境变量和父shell的数组

时间:2014-07-26 15:36:56

标签: linux bash shell vagrant sh

在Ubuntu 14.04上以root身份安装Ruby Version Manager(RVM)之后。我遇到了一个奇怪的bash行为。我们来看看导出的环境变量。我以ubunutu用户身份登录并在我的bash中运行export。以下是rvm的三个导出环境变量,其他可用:

declare -ax chpwd_functions='([0]="__rvm_cd_functions_set" [1]="__rvm_after_cd")'
declare -x rvm_version="1.25.28 (stable)"
declare -x rvm_ruby_mode

一切都很好,但是当我运行bash -c export时,我们只得到:

declare -x rvm_version="1.25.28 (stable)"

有人可以解释为什么在子bash中删除所有空的环境变量和所有数组?我该怎么做才能确保父shell中的所有环境变量真的可以在子shell中使用?

这个问题对我来说真是一个阻碍者。我正在使用vagrant及其shell配置程序。在一个脚本中我设置了rvm,在第二个脚本中我必须配置一些gemsets。问题是在第二个脚本中rvm命令不运行。活动shell仅获取rvm的那些环境变量,它们是非数组且非空。手动采购rvm.sh不是解决办法!

2 个答案:

答案 0 :(得分:2)

这是因为man bash的最后一行:

  

可能尚未导出数组变量。

我在某处读到BASH开发人员的一个注释,因为导出数组非常复杂且容易出错。

这一行:

declare -x rvm_ruby_mode

仅声明具有导出属性集(没有值)的变量的名称,如果为其分配值,则它将在子shell中可用。

<强> Here is post by BASH author on export of array in BASH.

答案 1 :(得分:1)

使用=运算符为名称指定值时会创建变量,例如

foo=bar

创建一个名为foo的变量,其值为bar

使用

declare有两个原因:一,允许动态创建变量(这超出了本问题的范围),另外两个,设置名称的属性(不是必然变量)。命令

declare -x rvm_ruby_mode

只需设置名称 rvm_ruby_mode的导出属性即可。要实际创建名称具有export属性集的变量,您需要使用=运算符,就像没有declare命令一样。

declare -x rvm_ruby_mode=

现在 rvm_ruby_mode是一个空变量,其名称标记为导出。

我说&#34;标记为出口&#34;因为在创建子shell之前不会导出变量。在此之前,只有一个名称列表,如果名称在创建子shell /子进程时具有值,则会复制到新环境中。此列表与实际变量列表(也是具有关联值的名称)分开。

至于为什么无法导出数组?从技术上讲,环境不是一组变量,因为变量是shell构造,而环境是POSIX中所有进程使用的东西,无论是否由shell运行。环境只是<name>=<value>形式的字符串列表。没有关于如何将数组元素打包成单个字符串的标准,任何进程都可以解析并重构为适当的数据结构。虽然bash可能会导致异常,但如果新的子进程是另一个bash shell并且想出一些在环境中嵌入数组的方法(就像它对函数一样)定义),显然这还没有完成。