zoukankan      html  css  js  c++  java
  • Bash 中的环境变量

    在 Bash 里,可以通过 export 命令查看当前 Shell 进程的环境变量,这些环境变量一些是 Bash 自己创建的,还有一些是 Bash 从父进程继承来的,然而需要注意的是,父进程传给 Bash 的环境变量不一定是我们想象的那样。

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

    "foo=1", "bar=2"

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

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

    甚至这样:

    "foo
    bar=1"

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

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

    att_exported | att_imported

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

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

    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 rm -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 在启动的时候就丢弃了,所以也就没法传递给它的子进程了。

  • 相关阅读:
    Vue整合nginx:(1)开发环境npm run dev下,通过nginx解决前后端分离造成的跨域问题
    SpringBoot 整合 ActiveMq
    SpringBoot 整合 slf4j 日志打印
    Java 抽象类的简单使用
    MongoDB基本使用
    node.js修改全局安装文件路径
    Vue + iview框架,搭建项目遇到的相关问题记录
    ThinkPHP重写路由,掩藏public/index.php
    thinkPhP + Apache + PHPstorm整合框架
    Ionic3,装饰器(@Input、@ViewChild)以及使用 Events 实现数据回调中的相关用法(五)
  • 原文地址:https://www.cnblogs.com/ziyunfei/p/4807122.html
Copyright © 2011-2022 走看看