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

时间:2021-07-14 23:01:24

On Unix, is there any way that one process can change another's environment variables (assuming they're all being run by the same user)? A general solution would be best, but if not, what about the specific case where one is a child of the other?

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

Edit: How about via gdb?

编辑:通过gdb怎么样?

10 个解决方案

#1


107  

Via gdb:

通过广东发展银行:

(gdb) attach process_id

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

(gdb) detach

This is quite a nasty hack and should only be done in the context of a debugging scenario, of course.

这是一个非常讨厌的技巧,当然,应该只在调试场景的上下文中进行。

#2


19  

You probably can do it technically (see other answers), but it might not help you.

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

Most programs will expect that env vars cannot be changed from the outside after startup, hence most will probably just read the vars they are interested in at startup and initialize based on that. So changing them afterwards will not make a difference, since the program will never re-read them.

大多数程序会期望在启动后,env vars不能从外部更改,因此大多数程序可能只会读取它们在启动时感兴趣的vars,并基于此进行初始化。所以之后改变它们不会有什么不同,因为程序永远不会重新阅读它们。

If you posted this as a concrete problem, you should probably take a different approach. If it was just out of curiosity: Nice question :-).

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

#3


13  

Substantially, no. If you had sufficient privileges (root, or thereabouts) and poked around /dev/kmem (kernel memory), and you made changes to the process's environment, and if the process actually re-referenced the environment variable afterwards (that is, the process had not already taken a copy of the env var and was not using just that copy), then maybe, if you were lucky and clever, and the wind was blowing in the right direction, and the phase of the moon was correct, perhaps, you might achieve something.

实质上,不。如果您有足够的权限(根,左右)和探头探脑/dev/kmem(内核内存),和你的变化进程的环境,如果这个过程实际上re-referenced之后环境变量(即过程还没有env var的副本,不是仅仅使用复印件),那么,如果你是幸运的,聪明的,风吹着正确的方向,和月亮的相位是正确的,也许,你会有所成就。

#4


7  

Quoting Jerry Peek:

引用杰瑞Peek:

You can't teach an old dog new tricks.

老狗学不了新把戏。

The only thing you can do is to change the environment variable of the child process before starting it: it gets the copy of the parent environment, sorry.

您惟一能做的就是在启动子进程之前更改该子进程的环境变量:它将获得父环境的副本,对不起。

See http://www.unix.com.ua/orelly/unix/upt/ch06_02.htm for details.

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

Just a comment on the answer about using /proc. Under linux /proc is supported but, it does not work, you cannot change the /proc/${pid}/environ file, even if you are root: it is absolutely read-only.

关于使用/proc的问题的回答。在支持linux /proc的情况下,您不能更改/proc/${pid}/ environment文件,即使您是root用户:它是绝对只读的。

#5


5  

I could think of the rather contrived way to do that, and it will not work for arbitrary processes.

我可以想出一种相当做作的方法来实现这一点,但它不会对任意过程起作用。

Suppose that you write your own shared library which implements 'char *getenv'. Then, you set up 'LD_PRELOAD' or 'LD_LIBRARY_PATH' env. vars so that both your processes are run with your shared library preloaded.

假设您编写自己的共享库来实现“char *getenv”。然后,设置“LD_PRELOAD”或“LD_LIBRARY_PATH”env。vars,使您的两个进程都在预加载的共享库中运行。

This way, you will essentially have a control over the code of the 'getenv' function. Then, you could do all sorts of nasty tricks. Your 'getenv' could consult external config file or SHM segment for alternate values of env vars. Or you could do regexp search/replace on the requested values. Or ...

这样,您就可以控制“getenv”函数的代码。然后,你可以做各种各样的恶作剧。您的“getenv”可以咨询外部配置文件或SHM段以替换env vars的值。或者可以对所请求的值执行regexp搜索/替换。还是……

I can't think of an easy way to do that for arbitrary running processes (even if you are root), short of rewriting dynamic linker (ld-linux.so).

对于任意运行的进程(即使您是root用户),我想不出一种简单的方法来实现这一点,除了重写动态链接器(ld- linuxso)。

#6


2  

Not as far as I know. Really you're trying to communicate from one process to another which calls for one of the IPC methods (shared memory, semaphores, sockets, etc.). Having received data by one of these methods you could then set environment variables or perform other actions more directly.

就我所知。实际上,您正在尝试从一个进程通信到另一个进程,该进程调用一个IPC方法(共享内存、信号量、套接字等)。通过这些方法之一接收数据之后,您可以设置环境变量或更直接地执行其他操作。

#7


2  

Or get your process to update a config file for the new process and then either:

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

  • perform a kill -HUP on the new process to reread the updated config file, or
  • 在新进程上执行kill -HUP以重新读取更新的配置文件,或者
  • have the process check the config file for updates every now and then. If changes are found, then reread the config file.
  • 让过程不时检查配置文件的更新。如果发现了更改,那么请重新阅读配置文件。

HTH.

HTH。

cheers,

欢呼,

Rob

罗伯

#8


1  

If your unix supports the /proc filesystem, then it's trivial to READ the env - you can read the environment, commandline, and many other attributes of any process you own that way. Changing it... Well, I can think of a way, but it's a BAD idea.

如果您的unix支持/proc文件系统,那么读取env是很简单的——您可以通过这种方式读取环境、命令行和任何进程的许多其他属性。改变它…我能想出个办法,但这主意不好。

The more general case... I don't know, but I doubt there's a portable answer.

更一般的情况下……我不知道,但我怀疑是否有现成的答案。

(Edited: my original answer assumed the OP wanted to READ the env, not change it)

(编辑:我最初的回答假设OP想读env,而不是修改它)

#9


1  

UNIX is full of Inter-process communication. Check if your target instance has some. Dbus is becoming a standard in "desktop" IPC.

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

I change environment variables inside of Awesome window manager using awesome-client with is a Dbus "sender" of lua code.

我使用Awesome -client with是lua代码的Dbus“sender”,在Awesome window manager内部更改环境变量。

#10


1  

Not a direct answer but... Raymond Chen had a [Windows-based] rationale around this only the other day :-

不是直接的回答,但是……就在前几天,Raymond Chen就有一个(基于windows的)理论:-

... Although there are certainly unsupported ways of doing it or ways that work with the assistance of a debugger, there’s nothing that is supported for programmatic access to another process’s command line, at least nothing provided by the kernel. ...

…虽然在调试器的帮助下,当然有一些不受支持的方法或方法,但是没有任何支持对另一个进程的命令行进行编程访问,至少内核没有提供任何支持。

That there isn’t is a consequence of the principle of not keeping track of information which you don’t need. The kernel has no need to obtain the command line of another process. It takes the command line passed to the CreateProcess function and copies it into the address space of the process being launched, in a location where the GetCommandLine function can retrieve it. Once the process can access its own command line, the kernel’s responsibilities are done.

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

Since the command line is copied into the process’s address space, the process might even write to the memory that holds the command line and modify it. If that happens, then the original command line is lost forever; the only known copy got overwritten.

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

In other words, any such kernel facilities would be

换句话说,任何这样的内核设施都是

  • difficult to implement
  • 难以实现
  • potentially a security concern
  • 一个潜在的安全问题

However the most likely reason is simply that there's limited use cases for such a facility.

然而,最可能的原因仅仅是这样一个工具的用例是有限的。

#1


107  

Via gdb:

通过广东发展银行:

(gdb) attach process_id

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

(gdb) detach

This is quite a nasty hack and should only be done in the context of a debugging scenario, of course.

这是一个非常讨厌的技巧,当然,应该只在调试场景的上下文中进行。

#2


19  

You probably can do it technically (see other answers), but it might not help you.

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

Most programs will expect that env vars cannot be changed from the outside after startup, hence most will probably just read the vars they are interested in at startup and initialize based on that. So changing them afterwards will not make a difference, since the program will never re-read them.

大多数程序会期望在启动后,env vars不能从外部更改,因此大多数程序可能只会读取它们在启动时感兴趣的vars,并基于此进行初始化。所以之后改变它们不会有什么不同,因为程序永远不会重新阅读它们。

If you posted this as a concrete problem, you should probably take a different approach. If it was just out of curiosity: Nice question :-).

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

#3


13  

Substantially, no. If you had sufficient privileges (root, or thereabouts) and poked around /dev/kmem (kernel memory), and you made changes to the process's environment, and if the process actually re-referenced the environment variable afterwards (that is, the process had not already taken a copy of the env var and was not using just that copy), then maybe, if you were lucky and clever, and the wind was blowing in the right direction, and the phase of the moon was correct, perhaps, you might achieve something.

实质上,不。如果您有足够的权限(根,左右)和探头探脑/dev/kmem(内核内存),和你的变化进程的环境,如果这个过程实际上re-referenced之后环境变量(即过程还没有env var的副本,不是仅仅使用复印件),那么,如果你是幸运的,聪明的,风吹着正确的方向,和月亮的相位是正确的,也许,你会有所成就。

#4


7  

Quoting Jerry Peek:

引用杰瑞Peek:

You can't teach an old dog new tricks.

老狗学不了新把戏。

The only thing you can do is to change the environment variable of the child process before starting it: it gets the copy of the parent environment, sorry.

您惟一能做的就是在启动子进程之前更改该子进程的环境变量:它将获得父环境的副本,对不起。

See http://www.unix.com.ua/orelly/unix/upt/ch06_02.htm for details.

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

Just a comment on the answer about using /proc. Under linux /proc is supported but, it does not work, you cannot change the /proc/${pid}/environ file, even if you are root: it is absolutely read-only.

关于使用/proc的问题的回答。在支持linux /proc的情况下,您不能更改/proc/${pid}/ environment文件,即使您是root用户:它是绝对只读的。

#5


5  

I could think of the rather contrived way to do that, and it will not work for arbitrary processes.

我可以想出一种相当做作的方法来实现这一点,但它不会对任意过程起作用。

Suppose that you write your own shared library which implements 'char *getenv'. Then, you set up 'LD_PRELOAD' or 'LD_LIBRARY_PATH' env. vars so that both your processes are run with your shared library preloaded.

假设您编写自己的共享库来实现“char *getenv”。然后,设置“LD_PRELOAD”或“LD_LIBRARY_PATH”env。vars,使您的两个进程都在预加载的共享库中运行。

This way, you will essentially have a control over the code of the 'getenv' function. Then, you could do all sorts of nasty tricks. Your 'getenv' could consult external config file or SHM segment for alternate values of env vars. Or you could do regexp search/replace on the requested values. Or ...

这样,您就可以控制“getenv”函数的代码。然后,你可以做各种各样的恶作剧。您的“getenv”可以咨询外部配置文件或SHM段以替换env vars的值。或者可以对所请求的值执行regexp搜索/替换。还是……

I can't think of an easy way to do that for arbitrary running processes (even if you are root), short of rewriting dynamic linker (ld-linux.so).

对于任意运行的进程(即使您是root用户),我想不出一种简单的方法来实现这一点,除了重写动态链接器(ld- linuxso)。

#6


2  

Not as far as I know. Really you're trying to communicate from one process to another which calls for one of the IPC methods (shared memory, semaphores, sockets, etc.). Having received data by one of these methods you could then set environment variables or perform other actions more directly.

就我所知。实际上,您正在尝试从一个进程通信到另一个进程,该进程调用一个IPC方法(共享内存、信号量、套接字等)。通过这些方法之一接收数据之后,您可以设置环境变量或更直接地执行其他操作。

#7


2  

Or get your process to update a config file for the new process and then either:

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

  • perform a kill -HUP on the new process to reread the updated config file, or
  • 在新进程上执行kill -HUP以重新读取更新的配置文件,或者
  • have the process check the config file for updates every now and then. If changes are found, then reread the config file.
  • 让过程不时检查配置文件的更新。如果发现了更改,那么请重新阅读配置文件。

HTH.

HTH。

cheers,

欢呼,

Rob

罗伯

#8


1  

If your unix supports the /proc filesystem, then it's trivial to READ the env - you can read the environment, commandline, and many other attributes of any process you own that way. Changing it... Well, I can think of a way, but it's a BAD idea.

如果您的unix支持/proc文件系统,那么读取env是很简单的——您可以通过这种方式读取环境、命令行和任何进程的许多其他属性。改变它…我能想出个办法,但这主意不好。

The more general case... I don't know, but I doubt there's a portable answer.

更一般的情况下……我不知道,但我怀疑是否有现成的答案。

(Edited: my original answer assumed the OP wanted to READ the env, not change it)

(编辑:我最初的回答假设OP想读env,而不是修改它)

#9


1  

UNIX is full of Inter-process communication. Check if your target instance has some. Dbus is becoming a standard in "desktop" IPC.

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

I change environment variables inside of Awesome window manager using awesome-client with is a Dbus "sender" of lua code.

我使用Awesome -client with是lua代码的Dbus“sender”,在Awesome window manager内部更改环境变量。

#10


1  

Not a direct answer but... Raymond Chen had a [Windows-based] rationale around this only the other day :-

不是直接的回答,但是……就在前几天,Raymond Chen就有一个(基于windows的)理论:-

... Although there are certainly unsupported ways of doing it or ways that work with the assistance of a debugger, there’s nothing that is supported for programmatic access to another process’s command line, at least nothing provided by the kernel. ...

…虽然在调试器的帮助下,当然有一些不受支持的方法或方法,但是没有任何支持对另一个进程的命令行进行编程访问,至少内核没有提供任何支持。

That there isn’t is a consequence of the principle of not keeping track of information which you don’t need. The kernel has no need to obtain the command line of another process. It takes the command line passed to the CreateProcess function and copies it into the address space of the process being launched, in a location where the GetCommandLine function can retrieve it. Once the process can access its own command line, the kernel’s responsibilities are done.

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

Since the command line is copied into the process’s address space, the process might even write to the memory that holds the command line and modify it. If that happens, then the original command line is lost forever; the only known copy got overwritten.

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

In other words, any such kernel facilities would be

换句话说,任何这样的内核设施都是

  • difficult to implement
  • 难以实现
  • potentially a security concern
  • 一个潜在的安全问题

However the most likely reason is simply that there's limited use cases for such a facility.

然而,最可能的原因仅仅是这样一个工具的用例是有限的。