Python 没有 root 的不可见环境变量 USERNAME

Python invisible environment variable USERNAME without root

出于安全和方便的目的,我想使用环境变量来存储一些凭据和一些其他信息。我已经将一些放入 /etc/environment,获取它并检查这两个变量对 root 用户和普通用户都是可见的:

$ cat /etc/environment
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
MAIL_PASSWORD="pwd"
USERNAME="un"
$ source /etc/environment
$ echo $USERNAME ";" $MAIL_PASSWORD
un ; pwd
$ sudo echo $USERNAME ";" $MAIL_PASSWORD
un ; pwd

然后我开始 python shell(还表明当我使用脚本并像 python3 test.py 那样调用它时这种行为仍然存在)并尝试获取此变量:

$ python3
Python 3.8.6 (default, Jan 27 2021, 15:42:20) 
[GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> print(os.getenv('MAIL_PASSWORD'))
pwd
>>> print(os.getenv('USERNAME'))
None
>>> 

嗯,其中一个肯定没问题,但另一个不知何故被隐藏了。试图找出这种行为的原因我尝试了同样的 root 权限:

$ sudo python3
Python 3.8.6 (default, Jan 27 2021, 15:42:20) 
[GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> print(os.getenv('MAIL_PASSWORD'))
pwd
>>> print(os.getenv('USERNAME'))
un
>>> 

现在一切正常。

我很困惑,因为这个问题与变量名有关。我尝试将 USERNAME 重命名为 USER,它成功了,变量 $USER 对于 python 和 shell 都是可见的。所以变量名USERNAME有问题,但我在文档中找不到关于它的信息。

谁能解释观察到的结果?我当然可以忽略它,并使用另一个变量名,但找到解释可能会很有趣。

如果有关系,我是运行 ubuntu 20.10,这个问题最先发现是ubuntu 20.04。 Python 仅测试 3.8 版本。

Could anyone explain the observed results?

结果可以解释为:

  • 您没有 reboot/re-login/refresh PAM 会话。
  • MAIL_PASSWORD变量在当前shell导出。
  • 未导出 USERNAME 变量。
 $ python3

您采购了 /etc/environemnt。变量 USERNAME 未导出。它不会传递给子进程的环境。 python 是一个子进程。所以它没有变量集。但是MAIL_PASSWORD是在parentshell中导出的,所以设置了

$ sudo python3

sudo 打开 pam 到 运行 pam_env 来源和解析 /etc/environemnt。变量由 pam_env 导出。因此,变量在子进程中可见。

I wanted to use environmental variables to store some credentials and some other information for security and convenience purposes

太棒了!所以,基于意见:

  • 如果您希望您的变量仅在 PAM 会话中可见(在您使用密码登录后),请将它们放在 /etc/environment/etc/security/pam_env.conf 中。参见 man environment。此外,这将为您工作站上的所有用户导出变量。我说你应该很少或永远不要使用 /etc/environment.
  • 为所有 Bourne 兼容登录的整个工作站推荐 shells:如果您希望变量在 shell 登录会话中可见,请将其设置为 /etc/profile,或者最好如果您的发行版支持,请将文件添加到 /etc/profile.d。请记住保持 POSIX sh 兼容语法。
  • 类似,对于 csh 兼容 shells 有 /etc/csh.login/etc/profile.d/*.csh
  • 如果您想为您的用户设置变量,仅登录 shells,请使用 ~/.profile。对于 bash-仅 ~/.bash_profile.
  • 建议,对于单个用户:为任何新的交互 bash shell 设置变量,只需使用 ~/.bashrc