在Unix上,是否有任何方法可以改变一个进程的环境变量(假设它们都由同一用户运行)?通用的解决方案是最好的,但是如果不是,那么一个孩子是另一个孩子的特殊情况又如何呢?
编辑:如何通过gdb?
在Unix上,是否有任何方法可以改变一个进程的环境变量(假设它们都由同一用户运行)?通用的解决方案是最好的,但是如果不是,那么一个孩子是另一个孩子的特殊情况又如何呢?
编辑:如何通过gdb?
Answers:
通过gdb:
(gdb) attach process_id
(gdb) call putenv ("env_var_name=env_var_value")
(gdb) detach
当然,这是一个令人讨厌的技巧,仅应在调试场景的情况下进行。
ptrace: Operation not permitted
基本上没有。如果您具有足够的特权(root或大约特权)并在/ dev / kmem(内核内存)中戳,并且您对进程的环境进行了更改,并且该进程之后是否实际重新引用了环境变量(即该进程)尚未制作过env var的副本,并且不只是使用该副本),也许,如果您很幸运和聪明,风向正确的方向吹来,月亮的相位是正确的,也许,你可能会有所成就。
gdb
在父进程上启动并被脚本化为可以进行更改,并且该脚本可以在不崩溃父进程的情况下工作。好的-您可能可以做到,但这不是您日常要做的事情。因此,出于实际目的,答案仍然是“ 否”。其余的答案涵盖了理论上可行的替代方案,有些可行的替代方案。
引用杰里·皮克(Jerry Peek):
你不能教老狗新的花样。
您唯一可以做的就是在更改子进程的环境变量之前启动:抱歉,它获取了父环境的副本。
有关详细信息,请参见http://www.unix.com.ua/orelly/unix/upt/ch06_02.htm。
只是对有关使用/ proc的答案的评论。在linux下,支持/ proc,但它不起作用,即使您是root用户,也无法更改/proc/${pid}/environ
文件:它绝对是只读的。
我可以想到这样做的相当人为的方法,它不适用于任意过程。
假设您编写了自己的实现“ char * getenv”的共享库。然后,您设置“ LD_PRELOAD”或“ LD_LIBRARY_PATH”环境。vars,这样您的两个进程都将在预加载共享库的情况下运行。
这样,您将基本上可以控制“ getenv”函数的代码。然后,您可以进行各种讨厌的把戏。您的“ getenv”可以查询外部配置文件或SHM段以获取env vars的备用值。或者,您可以对请求的值进行正则表达式搜索/替换。要么 ...
我想不出一种简单的方法来对任意正在运行的进程(即使您是root用户)执行此操作,而无需重写动态链接程序(ld-linux.so)。
如果您的Unix支持/ proc文件系统,那么读取环境很简单-您可以以这种方式读取任何进程的环境,命令行和许多其他属性。更改它...好吧,我可以想到一种方法,但这是一个坏主意。
更一般的情况...我不知道,但我怀疑是否有一个可移植的答案。
(编辑:我的原始答案假设OP想要读取环境,而不是更改它)
不是直接的答案,而是…… Raymond Chen前几天对此有[基于Windows]的基本原理:-
...尽管肯定有不受支持的执行方法或在调试器的协助下工作的方法,但是对以编程方式访问另一个进程的命令行不提供任何支持,至少内核不提供任何支持。...
不存在是由于不跟踪不需要的信息这一原则的结果。内核无需获取其他进程的命令行。它接受传递给该
CreateProcess
函数的命令行,并将其复制到正在启动的进程的地址空间中,该位置GetCommandLine
可以找到该函数。一旦进程可以访问其自己的命令行,就完成了内核的职责。由于命令行已复制到进程的地址空间中,因此进程甚至可能会写入保存命令行的内存并对其进行修改。如果发生这种情况,那么原始命令行将永远丢失;唯一已知的副本被覆盖。
换句话说,任何这样的内核功能都是
但是,最可能的原因仅仅是这种工具的用例有限。
看来putenv现在不起作用,但是setenv可以。我在尝试在当前外壳程序中设置变量时测试了可接受的答案,但没有成功
$] 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