【问题标题】:Child shell does not get empty environment variables and arrays of parent shell子shell没有得到空的环境变量和父shell的数组
【发布时间】:2014-07-27 02:08:17
【问题描述】:

在 Ubuntu 14.04 上以 root 身份安装 Ruby 版本管理器 (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 及其外壳配置程序。在一个脚本中,我设置了 rvm,而在第二个脚本中,我必须配置一些 gemset。问题是在第二个脚本中 rvm 命令不运行。活动 shell 只获取 rvm 的那些环境变量,它们是非数组和非空的。手动采购rvm.sh 是没有办法的!

【问题讨论】:

    标签: linux bash shell vagrant sh


    【解决方案1】:

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

    数组变量可能(尚未)被导出。

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

    还有这一行:

    declare -x rvm_ruby_mode
    

    只是声明了一个带有导出属性集的变量的名称(没有值),如果你给它一个值,它将在子shell中可用。

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

    【讨论】:

    • 感谢您的回答...但这不是外壳的无关紧要的行为。如您所见,数组已正确导出,因此通常支持数组。但只有在子外壳的情况下,所有数组都会被删除,表明它们不受支持。
    • declare -ax chpwd_functions 只是声明一个数组,但是当 sub shell 被分叉时,BASH 导出所有变量 except 数组变量。
    • Read this post by BASH author 关于导出数组变量。
    • 从技术上讲,rvm_ruby_mode 甚至不是一个空变量,只是一个带有导出属性集的名称。
    • 是的没错,declare -x rvm_ruby_mode 声明了一个变量但仅仅声明了一个变量的名称。
    【解决方案2】:

    当使用= 运算符为名称分配值时创建变量,例如

    foo=bar
    

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

    declare 用于两个原因:一,允许动态创建变量(这超出了本问题的范围),二,设置 names 上的属性(不一定是变量)。命令

    declare -x rvm_ruby_mode
    

    只需设置 name rvm_ruby_mode 的导出属性。要实际创建一个名称设置了导出属性的变量,您需要使用= 运算符,就像不使用declare 命令一样。

    declare -x rvm_ruby_mode=
    

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

    我说“标记为导出”是因为在创建子shell 之前不会导出变量。在那之前,只有一个名称列表,如果在创建子外壳/子进程时名称具有值,则将其复制到新环境中。该列表与实际变量列表(同样是具有关联值的名称)分开。

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

    【讨论】:

    • 非常感谢!这很有帮助。所以变量rvm_ruby_mode 只被声明但尚未定义。如果一个值被赋值并且 bash 只导出定义的和非数组的变量,它就会被定义,对吧?
    • 我不会说 rvm_ruby_mode 已声明(bash 没有变量声明);它只是在 name 上标记一个属性,而不用该名称定义变量。但抛开术语不谈,您的理解是正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    • 1970-01-01
    • 2023-03-30
    • 2013-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多