简体   繁体   中英

Permanently setting environment variables from a C++ program after exit

I am writing a bash script that runs a C++ program multiple times. I use getenv() and putenv() to create, get, and update environment variables in the C++ program. After the C++ program ends, the bash script needs to grab these variables and perform some basic logic. The problem is that when the C++ program exits, the environment variables disappear. Is there any way to permanently store these variables after the program's termination so that the bash script can use them? If not, what is the best way to share variables between a bash script and a C++ program? The only solution I can think of is writing output to files. I do not want to print this data in the console. Any help would be greatly appreciated.

Each process has its own copy of the environment variables, which are initialised by copying them from the parent process when the new process is launched. When you change an environment variable in your process, the parent process has no knowledge of this.

In order to pass back information from a child to a parent, you will need to set up some other kind of communications channel. It could be files on disk, or a pipe, or (depending on the capabilities of your parent, bash might not be able to do all this) shared memory or some other IPC mechanism. The parent program would then be responsible for changing its own environment variables based on information received from the child.

我个人只能在16位DOS汇编程序中执行此操作,通过跟踪指向前一个进程的指针直到它指向自身,这意味着您已到达COMMAND.COM的第一个实例,然后更改了它手动环境。

If your program returned the variables via standard output as string, like this:

FOO=23; BAR=45;

Then, bash could call it like this:

eval `./your_program`

end $FOO and $BAR will be accessible to bash.

To test this try:

eval `echo "FOO=23; BAR=45;"`
echo "$FOO $BAR"

Of course, in this method the program does not change environment variables of calling process (which is not possible), but just returns a string that is then evaluated by bash and the evaluation sets the variables.

Do not use this method if your program processes input from not trusted source. If someone tricked your program to print "rm -rf /" to the standard output you would be doomed.

As far as i know under a "standard" GNU/Linux environment you can set environment variables in 3 ways:

  • using command line utilities like export
  • editing files like ~/.profile or ~/.bashrc for an user or the equivalent files under /etc for system
  • feeding temporary values to a command like this CXX=g++ CUSTOM_VERSION=2.5 command

the last one is usually used to customize builds and it's good because doesn't harm the system and does not interfere with any system settings or values or files and everything is back to normal after the execution of the command. It's the best way if you like to have a temporary modification for a particular set of variables.

There is no way for a program to set environment variables in its parent. Or, well, no legitimate way. Hacking into its process with ptrace does not count. :-)

What you should do is output the environment variables on standard output. Have the shell script read them and set them. If the environment variables are all that you output the call is very simple:

`program`

The back-ticks will capture the output of the program. Then it will replace the back-ticks with the output. Which will be commands to set shell variables. Then later in your shell script be sure to do:

export VAR1
export VAR2

You need the export commands in order to move them into the environment that is passed to programs launched from the shell.

You cannot set environment variables which survive the life-time of your process, so the easiest solution is to write to output files as you suggested or write to specific filehandles handed down from Bash:

C++:

int main (int argc, char* argv[])
{
   // missing error handling
   int fd = atoi(argv[1]);
   const char* env = "BLAH=SMURF";
   write(5, env, strlen(env));
   return 0;
}

Bash:

# discard stdout and stderr, redirect 5 to stdout so that it can be captured
# and tell the process that it should write to 5 (the first 5)
VARIABLES=`./command 5 2>&1 1>/dev/null 5>&1`

This is probably a crack-pot idea but it should work :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM