在大多数使用 bash 的 *nix 环境中,您将更改用户本地的环境变量~/.bash_profile
或类似文件,然后source
更改更改的文件,以使更改在您的会话中生效。
同样,在更改后source
执行 ing/etc/profile
将使这些更改在您当前的会话中生效。
但是假设您需要更改在 中/etc/profile
(或在 下某处/etc/profile.d/
)定义的环境变量,并且希望更改立即在系统上所有用户的所有会话中可见。如何在不重新启动系统的情况下实现这一目标?
答案1
您可以强制所有登录的用户注销,然后再次登录(并终止并重新启动由使用 /etc/profile 的 shell 启动的任何守护进程)。不需要重新启动。
除此之外,你不能。
您所能做的就是在每个需要新定义的 shell 会话中单独获取 /etc/profile ......但这只会影响您可以实际运行source /etc/profile
或. /etc/profile
使用的 shell - 例如,您不能直接更改现有环境已经运行的进程(例如正在运行的 X 会话)。
子进程不能更改其父进程的环境。无论如何,不是直接的(父进程可以观察它的孩子做了什么并据此采取行动,包括改变它自己的环境......但这是完全不同的事情,并且需要被编程到父进程中)
答案2
事实上你不需要。
原因是,虽然环境变量在执行时传递给程序(与命令行参数的方式相同),但之后它们只是进程内存中某处的某个表。您无法从外部或另一个进程修改它们,因为一般来说你不知道他们在哪里。
C 库保留一个名为 的指针environ
,它指向一个指针表,这些指针指向统称为“环境”的值。如果在程序的生命周期内需要重新分配该表的位置,则该表的位置可能会发生变化,并且值的位置也会发生类似的变化。
在程序运行时,指针environ
本身将位于同一位置,因此只要找到指针,您就可以合理地破解这些值。地址空间布局随机化之类的东西会导致它在不同的程序调用中位于不同的位置。即使您要找到它并更改程序的内存,您也无法判断程序是否将该值(或其指针)复制到其他地方并从那里使用它。类似配置文件中的内容将被复制到程序内存中的某个位置。
在系统调用级别,环境甚至不会在程序的执行过程中自动复制,因为环境值必须作为参数显式传递给系统execve()
调用,并且传递到那里的表不需要具有与执行进程所称的任何关系environ
。
所有这些也意味着 Linux 中显示的内容可能与程序中系统调用返回的/proc/$pid/environ
内容不一致。 getenv()
(我认为该文件显示了程序执行时用于传递值的内存区域。)将“环境”作为某种特殊数据结构的想法并不完全正确。
要修改正在运行的程序的配置,您需要程序本身的支持,它需要能够从某处重新加载配置。或者至少来自其父级的支持,可以重新加载它是配置,然后重新启动子进程以向其传递另一组环境变量。