Bash 中的环境变量

在 Bash 里,能够经过 export 命令查看当前 Shell 进程的环境变量,这些环境变量一些是 Bash 本身建立的,还有一些是 Bash 从父进程继承来的,然而须要注意的是,父进程传给 Bash 的环境变量不必定是咱们想象的那样。数组

在 C 语言层面,环境变量是存放在一个名为 environ 的全局变量里的,这个变量的值是一个字符串的数组,像这样:bash

"foo=1", "bar=2"

在父子孙一辈辈进程中传递的就是这么个数组,咱们嘴里说的环境变量的原貌其实就是个字符串,而不是咱们一般在高级语言里看到的键值对。然而操做系统并无对环境变量字符串的格式作任何限制,environ 变量的值还能够是这样:ide

"1=1", "=2", "="

甚至这样:spa

"foo\nbar=1"

Bash 在启动的时候,会检查 environ 数组中的每一个字符串,若是它包含 =,且 = 左边有任意的字符,就把它从 = 分割开,一个作变量名,一个作值,变成本身的变量。咦? "1=1" 也会导入成变量? 是的,在 Bash 的实现当中,是这样的,只是这样的变量会被加上特殊的属性标记。操作系统

变量名称合法的变量被添加的属性是: code

att_exported | att_imported

一个表示是要导出给子进程的环境变量,一个表示是从环境变量导入的变量。blog

变量名不合法的变量被添加的属性是:继承

att_exported | att_imported | att_invisible

多了一个 invisible 属性,表示不可见。进程

在 Bash 启动以后,各个内部命令能够经过这个标记判断是否是本身想要的变量。好比 set 命令就不会输出 1 这个变量:字符串

$ env -i 1=1 bash -c set | grep '1='

 

但 export 命令就会:

$ env -i 1=1 bash -c export

declare -x 1 
declare -x OLDPWD
declare -x PWD="/Users/admin"
declare -x SHLVL="1"

declare -x 1 显然是非法的,甚至还能够这样:

$ env -i $'foo\nrm -rf /=' bash -c export

declare -x OLDPWD
declare -x PWD="/Users/admin"
declare -x SHLVL="1"
declare -x foo
rm -rf /

看起来颇有风险的样子,不过目前 Bash 4.4 beta 版本,已经修复了这个问题,export 命令再也不输出那些变量名不合法的变量了,下面是 export 命令源码作的改动:

+     /* If we imported a variable that's not a valid identifier, don't
+        show it in any lists. */
+     if ((var->attributes & (att_invisible|att_imported)) == (att_invisible|att_imported))
+        continue;

那 Bash 在启动其余程序的时候,会把这样的环境变量传递给子进程吗?答案是会的,咱们能够经过在两个 env 命令中间插入一个 bash 命令来看出效果:

$ env -i 1=1 bash -c env

PWD=/Users/admin
SHLVL=1
1=1
_=/usr/bin/env

Bash 在启动其余程序的时候,会把本身全部的变量中带有 att_exported 属性且值不是空的变量以及它们的值分别用 = 链接起来合成一个字符串数组,从新复值给 environ 变量,也就是作了和启动时导入环境变量相反的操做。

那些没有等号或者等号左边没有字符的环境变量,由于 Bash 在启动的时候就丢弃了,因此也就无法传递给它的子进程了。

相关文章
相关标签/搜索