我正在编写一个多次运行 C++ 程序的 bash 脚本。我使用getenv()
andputenv()
来创建、获取和更新 C++ 程序中的环境变量。C++程序结束后,bash脚本需要抓取这些变量并执行一些基本逻辑。问题是当C++程序退出时,环境变量消失了。有没有办法在程序终止后永久存储这些变量,以便 bash 脚本可以使用它们?如果不是,那么在 bash 脚本和 C++ 程序之间共享变量的最佳方式是什么?我能想到的唯一解决方案是将输出写入文件。我不想在控制台中打印这些数据。任何帮助将不胜感激。
6 回答
每个进程都有自己的环境变量副本,当新进程启动时,通过从父进程复制它们来初始化环境变量。当您更改进程中的环境变量时,父进程对此一无所知。
为了将信息从孩子传回给父母,您需要建立一些其他类型的沟通渠道。它可能是磁盘上的文件,或管道,或者(取决于您的父级的能力,bash
可能无法完成所有这些)共享内存或其他一些 IPC 机制。然后,父程序将负责根据从子程序接收到的信息更改自己的环境变量。
我个人只能在 16 位 DOS 汇编程序中做到这一点,通过跟踪指向前一个进程的指针直到它指向自身,这意味着你已经到达 COMMAND.COM 的第一个实例,然后更改了它的手动环境。
如果您的程序通过标准输出将变量作为字符串返回,如下所示:
FOO=23; BAR=45;
然后,bash 可以这样称呼它:
eval `./your_program`
bash 可以访问 end $FOO 和 $BAR。
要测试这个尝试:
eval `echo "FOO=23; BAR=45;"`
echo "$FOO $BAR"
当然,在这种方法中,程序不会改变调用进程的环境变量(这是不可能的),而只是返回一个字符串,然后由 bash 评估,评估设置变量。
如果您的程序处理来自不可信来源的输入,请不要使用此方法。如果有人欺骗您的程序将“rm -rf /”打印到标准输出,您将注定失败。
据我所知,在“标准”GNU/Linux 环境下,您可以通过 3 种方式设置环境变量:
- 使用命令行实用程序,例如
export
- 编辑类似
~/.profile
或~/.bashrc
为用户的文件或/etc
系统下的等效文件 - 将临时值提供给这样的命令
CXX=g++ CUSTOM_VERSION=2.5 command
最后一个通常用于自定义构建,它很好,因为它不会损害系统并且不会干扰任何系统设置或值或文件,并且在执行命令后一切都恢复正常。如果您想对一组特定的变量进行临时修改,这是最好的方法。
程序无法在其父项中设置环境变量。或者,好吧,没有合法的方式。侵入其进程ptrace
不算在内。:-)
您应该做的是在标准输出上输出环境变量。让 shell 脚本读取并设置它们。如果环境变量是您输出的全部,则调用非常简单:
`program`
反引号将捕获程序的输出。然后它将用输出替换反引号。这将是设置 shell 变量的命令。然后稍后在您的 shell 脚本中确保执行以下操作:
export VAR1
export VAR2
您需要导出命令才能将它们移动到传递给从 shell 启动的程序的环境中。
您无法设置在进程生命周期中存在的环境变量,因此最简单的解决方案是按照您的建议写入输出文件或写入从 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`
这可能是一个疯狂的想法,但它应该可以工作:)