3

我正在编写一个多次运行 C++ 程序的 bash 脚本。我使用getenv()andputenv()来创建、获取和更新 C++ 程序中的环境变量。C++程序结束后,bash脚本需要抓取这些变量并执行一些基本逻辑。问题是当C++程序退出时,环境变量消失了。有没有办法在程序终止后永久存储这些变量,以便 bash 脚本可以使用它们?如果不是,那么在 bash 脚本和 C++ 程序之间共享变量的最佳方式是什么?我能想到的唯一解决方案是将输出写入文件。我不想在控制台中打印这些数据。任何帮助将不胜感激。

4

6 回答 6

5

每个进程都有自己的环境变量副本,当新进程启动时,通过从父进程复制它们来初始化环境变量。当您更改进程中的环境变量时,父进程对此一无所知。

为了将信息从孩子传回给父母,您需要建立一些其他类型的沟通渠道。它可能是磁盘上的文件,或管道,或者(取决于您的父级的能力,bash可能无法完成所有这些)共享内存或其他一些 IPC 机制。然后,父程序将负责根据从子程序接收到的信息更改自己的环境变量。

于 2012-10-14T20:10:34.643 回答
4

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

于 2012-11-21T18:22:43.020 回答
2

如果您的程序通过标准输出将变量作为字符串返回,如下所示:

FOO=23; BAR=45;

然后,bash 可以这样称呼它:

eval `./your_program`

bash 可以访问 end $FOO 和 $BAR。

要测试这个尝试:

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

当然,在这种方法中,程序不会改变调用进程的环境变量(这是不可能的),而只是返回一个字符串,然后由 bash 评估,评估设置变量。

如果您的程序处理来自不可信来源的输入,请不要使用此方法。如果有人欺骗您的程序将“rm -rf /”打印到标准输出,您将注定失败。

于 2012-10-14T20:16:41.590 回答
0

据我所知,在“标准”GNU/Linux 环境下,您可以通过 3 种方式设置环境变量:

  • 使用命令行实用程序,例如export
  • 编辑类似~/.profile~/.bashrc为用户的文件或/etc系统下的等效文件
  • 将临时值提供给这样的命令CXX=g++ CUSTOM_VERSION=2.5 command

最后一个通常用于自定义构建,它很好,因为它不会损害系统并且不会干扰任何系统设置或值或文件,并且在执行命令后一切都恢复正常。如果您想对一组特定的变量进行临时修改,这是最好的方法。

于 2012-10-14T20:12:20.587 回答
0

程序无法在其父项中设置环境变量。或者,好吧,没有合法的方式。侵入其进程ptrace不算在内。:-)

您应该做的是在标准输出上输出环境变量。让 shell 脚本读取并设置它们。如果环境变量是您输出的全部,则调用非常简单:

`program`

反引号将捕获程序的输出。然后它将用输出替换反引号。这将是设置 shell 变量的命令。然后稍后在您的 shell 脚本中确保执行以下操作:

export VAR1
export VAR2

您需要导出命令才能将它们移动到传递给从 shell 启动的程序的环境中。

于 2012-10-14T20:12:54.797 回答
0

您无法设置在进程生命周期中存在的环境变量,因此最简单的解决方案是按照您的建议写入输出文件或写入从 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;
}

重击:

# 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`

这可能是一个疯狂的想法,但它应该可以工作:)

于 2012-10-14T20:14:06.573 回答