3

我想知道是否有办法从 bash 进程设置环境变量并从另一个进程读取它。

由于环境变量的值对于进程来说是本地的(除了继承),因此不能只export FOO="bar"在终端中执行并从另一个终端中读取它。然后我试图让他们通过/proc/environ,但这就是我得到的:

etuardu@subranu:~$ FOO="foo" bash
etuardu@subranu:~$ strings /proc/$$/environ | grep FOO
FOO=foo
etuardu@subranu:~$ export FOO="bar"
etuardu@subranu:~$ strings /proc/$$/environ | grep FOO
FOO=foo
etuardu@subranu:~$ echo $FOO
bar

看来我可以得到该环境变量在进程开始时所具有的值。
它现在的价值如何?

4

1 回答 1

7

由于环境变量的工作方式,这通常是不可能的。

当一个进程第一次被exec编辑时,内核向它提供它的初始环境变量集以及其他一些东西(主要是它的argv向量,即它的命令行)。此后,此列表(如argv向量)只是进程内的常规 C 字符指针数组。该过程可以随意管理它们,包括完全回收保存字符串的内存以供其他用途(如果需要)。一个进程窥视任何其他进程的内存空间以查找其环境变量是不安全的。

大多数类型的进程确实或多或少地按原样使用内核提供的环境变量列表,可能会使用 和 之类的 C 库函数对其进行查询和getenv()修改putenv()。如果这些进程轮流运行任何其他可执行文件,它们会将相同的环境向量传递给execve它们在自己执行开始时收到的系统调用,这意味着新的可执行文件获得相同的环境(可能通过一些调用来增强putenv()) .

贝壳是另一回事。因为环境变量在 shell 脚本中非常重要,一些 shell 使用提供给它们的环境向量仅作为“起始值”,然后忽略它。他们使用自己的、更有能力的数据结构来管理他们的环境变量。当他们执行他们自己的子进程时,他们将一个全新的环境向量传递给新进程,由这些内部数据结构构建。这意味着即使您按照上面的建议查看 shell 的内存空间以查找其环境变量,您也只会找到初始设置,而不是 shell 实际使用的环境!

可以做的是查询进程的初始环境变量集,即在启动时传递给可执行文件的同一向量。但这不是可移植的,即使在支持它的操作系统之间也存在相当大的差异。例如,在历史上的 UNIX 中,它仍然有点难看,因为它仍然涉及窥探进程的内存空间(尽管是一个称为“用户区”的特殊内存区域)。Linux 更优雅地使这成为可能:向量可以作为文本字符串在/proc/<pid>/environ. 在大多数可以获得此信息的系统上,ps都有一个e能够显示它的选项。

于 2012-11-03T14:28:30.903 回答