tags:

views:

1483

answers:

10

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?

Edit: How about via gdb?

A: 

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.

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)

Mike G.
Ooops, edited my answer - I was assuming he wanted to read the env, not change it.
Mike G.
Don't leave me hanging. What's your bad idea?
raldi
On Linux, I believe you MIGHT be able to open /proc/<pid>/mem read-write for other process you own... I'm not sure, though. Trying, and actually messing with the environment, would DEFINITELY be a bad idea. So I'm not suggesting you try it...
Mike G.
A: 

Quoting Jerry 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.

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.

Davide
Which still leaves the question: where are env var values actually stored? Is that done by the kernel? Or does the shell store the values, and /proc/<pid>/environ gets them from there?
oliver
This is an implementation detail, and it might be a (separate) good question. I think every UNIX uses its own way for the storage, but all of them share the behavior described above, which is part of the specifications.
Davide
+1  A: 

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.

Stephen Darlington
A: 

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
  • have the process check the config file for updates every now and then. If changes are found, then reread the config file.

HTH.

cheers,

Rob

Rob Wells
+2  A: 

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.

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 ...

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).

ADEpt
+6  A: 

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.

Jonathan Leffler
+5  A: 

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.

Andrew
So this seems to imply that you can indeed change the environment of a process if you attach to the process as GDB does, and then detach. It seems it would be possible to write a program that does only this.
grieve
"It seems it would be possible to write a program that does only this" Indeed.. it is.
Longpoke
+1  A: 

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.

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

sleske
A: 

Not an answer, but a follow-up question. I found this discussion when searching for a solution to the following: in Linux/Gnome, is there a way to change or add environment variable defined in .bash_profile, without the need to re-login? In Windows, I remember, it was possible to change a variable in "My Computer" properties, and then all programs which were launched after that, saw the new value.

Dmitry Diskin