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

ral*_*ldi 93 unix linux shell gdb environment-variables

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

编辑:通过gdb怎么样?

An̲*_*rew 130

通过gdb:

(gdb) attach process_id

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

(gdb) detach
Run Code Online (Sandbox Code Playgroud)

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

  • 请注意,这仅适用于进程尚未在先前getenv之后永久缓存该值的情况. (10认同)
  • 所以这似乎暗示如果你像GDB那样附加到进程,你确实可以改变进程的环境,然后分离.似乎可以编写一个只执行此操作的程序. (8认同)
  • "似乎有可能编写一个只做这个的程序"确实......确实如此. (3认同)
  • 对于不使用cygwin编译的进程,它甚至可以在使用cygwin的Windows上运行! (2认同)
  • 在某些系统上,gdb 可能会给出以下错误:`'putenv' has unknown return type; 将调用转换为其声明的返回类型`; 在这些情况下,您应该将 `putenv` 调用更改为:`call (int) putenv ("env_var_name=env_var_value")` (2认同)

sle*_*ske 22

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

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

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


Jon*_*ler 13

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

  • 我没有得到答案. (2认同)
  • 那个gdb怎么样? (2认同)

Dav*_*ide 7

引用Jerry Peek:

你不能教老狗新技巧.

你唯一能做的就是启动之前更改子进程的环境变量:它获取父环境的副本,抱歉.

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

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


ADE*_*Ept 7

我可以想到这样做的相当人为的方法,它对任意过程都不起作用.

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

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

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


Kak*_*ake 5

看来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=
Run Code Online (Sandbox Code Playgroud)

以及它的工作原理的变体:

$] 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
Run Code Online (Sandbox Code Playgroud)