有没有办法在Unix中更改另一个进程的环境变量?

时间:2008-10-15 15:02:20

标签: linux shell unix gdb environment-variables

在Unix上,有没有办法让一个进程可以改变另一个进程的环境变量(假设它们都是由同一个用户运行)?一般的解决方案是最好的,但如果没有,那么一个人是另一个人的孩子的具体情况呢?

编辑:通过gdb怎么样?

11 个答案:

答案 0 :(得分:124)

通过gdb:

(gdb) attach process_id

(gdb) call putenv ("env_var_name=env_var_value")

(gdb) detach

这是一个非常讨厌的黑客攻击,当然应该只在调试场景的环境中完成。

答案 1 :(得分:21)

你可能在技术上可以做到(见其他答案),但它可能对你没有帮助。

大多数程序都希望启动后无法从外部更改env变量,因此大多数人可能只是在启动时读取他们感兴趣的变量并基于此进行初始化。因此,之后更改它们不会产生任何影响,因为程序永远不会重新读取它们。

如果您将此作为具体问题发布,您应该采取不同的方法。如果只是出于好奇:好问题: - )。

答案 2 :(得分:13)

基本上没有。如果你有足够的权限(root或其左右)并且在/ dev / kmem(内核内存)周围进行了调整,并且你对进程的环境进行了更改,并且之后进程实际上重新引用了环境变量(即进程)还没有拿过env var的副本并且没有使用那个副本),那么也许,如果你是幸运和聪明的,风向正确的方向吹,月亮的相位是正确的,也许,你可能会有所成就。

答案 3 :(得分:6)

引用Jerry Peek:

  

你不能教老狗新手法。

你唯一能做的就是在开始之前更改子进程的环境变量:它获取了父环境的副本,抱歉。

有关详细信息,请参阅http://www.unix.com.ua/orelly/unix/upt/ch06_02.htm

关于使用/ proc的答案的评论。在linux / proc下支持但是,它不起作用,你不能更改/proc/${pid}/environ文件,即使你是root用户:它是绝对只读

答案 4 :(得分:6)

我可以想到这样做的相当人为的方式,它不适用于任意过程。

假设您编写了自己的共享库,它实现了'char * getenv'。然后,设置'LD_PRELOAD'或'LD_LIBRARY_PATH'env。 vars,以便在预先加载共享库的情况下运行两个进程。

这样,您基本上可以控制'getenv'函数的代码。然后,你可以做各种令人讨厌的技巧。您的'getenv'可以查询外部配置文件或SHM段以获取env vars的备用值。或者您可以对请求的值执行regexp搜索/替换。或者......

我想不出一个简单的方法来为任意运行的进程(即使你是root用户)做到这一点,而不是重写动态链接器(ld-linux.so)。

答案 5 :(得分:3)

或让您的流程更新新流程的配置文件,然后:

  • 对新进程执行kill -HUP以重新读取更新的配置文件,或
  • 让进程不时检查配置文件中的更新。如果找到更改,则重新读取配置文件。

HTH。

欢呼声,

罗布

答案 6 :(得分:2)

据我所知。你真的想从一个进程通信到另一个进程,它需要一个IPC方法(共享内存,信号量,套接字等)。通过这些方法之一接收数据后,您可以更直接地设置环境变量或执行其他操作。

答案 7 :(得分:2)

看来 putenv 现在不起作用,但是 setenv 可以。 我正在尝试接受的答案,同时尝试在当前shell中设置变量,但没有成功

$] sudo gdb -p $$
(gdb) call putenv("TEST=1234")
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x0
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=

及其变体的工作方式:

$] sudo gdb -p $$
(gdb) call (int) setenv("TEST", "1234", 1)
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x55f19ff5edc0 "1234"
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=1234

答案 8 :(得分:1)

如果你的unix支持/ proc文件系统,那么读取env是微不足道的 - 你可以通过这种方式读取环境,命令行和任何进程的许多其他属性。改变它......好吧,我可以想办法,但这是一个不好的想法。

更一般的情况......我不知道,但我怀疑是否有便携式答案。

(编辑:我的原始答案假设OP想要阅读env,而不是更改它)

答案 9 :(得分:1)

不是直接答案,而是...... Raymond Chen had a [Windows-based] rationale around this only the other day: -

  

...虽然肯定有不支持的方法或者在调试器的帮助下工作的方式,但是对于编程访问另一个进程的命令行没有任何支持,至少内核没有提供任何内容。 ...

     

不存在不跟踪您不需要的信息的原则的结果。内核无需获取另一个进程的命令行。它将传递给CreateProcess函数的命令行并将其复制到正在启动的进程的地址空间中,在GetCommandLine函数可以检索它的位置。一旦进程可以访问自己的命令行,内核的职责就完成了。

     

由于命令行被复制到进程的地址空间,因此该进程甚至可以写入保存命令行的内存并对其进行修改。如果发生这种情况,那么原始命令行将永远丢失;唯一已知的副本被覆盖了。

换句话说,任何这样的内核工具都是

  • 难以实施
  • 可能是安全问题

然而,最可能的原因仅仅是这种设施的用例有限。

答案 10 :(得分:1)

UNIX充满了进程间通信。检查您的目标实例是否有一些。 Dbus正在成为“桌面”IPC的标准。

我使用 awesome-client 更改了Awesome窗口管理器中的环境变量,并且是lua代码的Dbus“发送者”。