观察:使用操作系统的“读取”实用程序设置的环境变量,其中包含纯数字值,在 Python 的os.environ[]
结构或节点的process.env
结构中无法访问,但 bash 可以访问。
预期的行为是所有环境变量都可以从应用程序中平等地访问,无论它们是如何创建的。
如果使用 bashexport N=12345
语法设置相同的变量,则可以访问。似乎使用 read 命令创建的变量不会以某种方式与其他变量相等,这会干扰节点/Python 解析这些变量的逻辑。
无法从 node/Python 访问的相同变量可以在 bash 命令行中轻松访问,如下面的 echo 语句所示。
read 命令根据键输入设置环境变量。这是一种在变量中输入秘密而不留下该秘密的 .bash_history 记录的便捷方式。
转载于:
- OSX 10.14.6(“Mojave”)Python 2.7、Python 3.6、节点 10.16.3 Linux
- 内核 3.10 CentOS 64 位,Python2.7.5
样本:
使用read
并提示用户输入名为 L 的环境变量的值。
~ $ read L
12345
~ $ python2
Python 2.7.16 (default, Apr 12 2019, 15:32:40)
[GCC 4.2.1 Compatible Apple LLVM 10.0.1 (clang-1001.0.46.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ["L"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/UserDict.py", line 40, in __getitem__
raise KeyError(key)
KeyError: 'L'
>>>
~ $ python3
Python 3.7.3 (default, Mar 27 2019, 09:23:15)
[Clang 10.0.1 (clang-1001.0.46.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ["L"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/os.py", line 678, in __getitem__
raise KeyError(key) from None
KeyError: 'L'
~ $ echo $L
12345
有趣的是,如果通过 read 命令以外的方式设置数值变量,它们可以在 Python 和 node.js 中访问。
>>> os.environ["HISTSIZE"]
'12345678'
在 shell 中,您不是在使用环境变量,而是在使用shell变量。shell 只是从其初始环境的副本开始,但它维护自己的变量命名空间。
Shell 变量只有在具有 'export' 标志的情况下才会被复制回环境。默认情况下不会导出全新的变量——不管它们是如何生成的,你仍然需要使用
export
命令在它们上设置正确的标志:再次注意,这不是特定于
read
. 如果您只是设置一个变量而不使用,您会看到同样的失败export
:在 bash 中,您可以
declare -p VAR
用来检查该变量当前是否被标记为导出到环境中(如果是,它将具有-x
选项)。(输出作为输入有效——例如,如果您实际运行
declare -x
,则相当于export
。)杂项说明:
环境只能包含字符串值,但 shell 变量不仅限于此——例如,大多数 shell 都有数组/列表和字典。
Shell 通常包含不想导出的变量。例如,$LINES 和 $COLUMNS 在 shell 本身内是动态的,但导出它们只会让程序看到静态值,这会导致问题。