有没有办法在 C 或 C++ 中嵌入 Sh/Bash 会话?

Is there a way to embed a Sh/Bash session in C or C++?

本文关键字:Sh Bash 会话 C++ 有没有      更新时间:2023-10-16

就像Python一样。

我不仅对运行单个 shell 命令感兴趣,而且对保存当前环境状态感兴趣。

例如,以下代码:

system("a=2");
system("echo $a");

什么都不打印,但我想找到一种程序打印"2"的方法。

主要目标是在整个 С/С++ 程序中保持 shell 环境(可以初始化,例如,使用 .bashrc(,就像您在终端中工作一样。

Bash 没有与 Python 相同的 API,但它是一个shell。 它具有基于文本的UI,其他程序相对容易使用。 您不能使用system(),因为它要求您预先指定所有 shell 输入并阻止直到 shell 退出,但您可以使用与system()相同的机制:在单独的进程中运行 shell。

细节取决于运行程序的机器,但在通常找到Bash或其他Bourne家族shell(Linux,Mac和其他POSIX系统(的机器上,您至少有两种主要的选择:

  1. 如果希望 shell 输出(仅(转到主机程序的标准输出和标准错误流,则可以使用popen()打开连接到 shell 的流:

    FILE *shell = popen("/bin/bash -i", "w");
    

    然后,您可以将任意序列的 shell 命令写入流,shell 将在其标准输入上接收它们,执行它们,并将结果写入其标准输出。 以这种方式启动的 shell 将共享调用方的标准输出和标准错误。

  2. 如果主机程序必须同时将输入馈送到 shell 并接收其输出,那么您需要在较低级别工作:

    • 使用pipe()创建两个管道(如果要单独捕获外壳的标准错误,则为三个管道(。
    • fork()运行 shell 的
    • 子进程,并在其中运行 shell
      1. 将适当的管道端端dup2()到子项的标准输入、输出和(可选(错误上。
      2. close()孩子不会使用的管端
      3. 在子进程中execl()外壳程序。
    • 回到父母,
      • close()父级不会使用的管道端
      • 通过为此设置的管道向命令行管理程序发送命令
      • 通过管道读取响应和/或错误响应
      • 使用外壳完成后,close()管道和wait()子进程终止。 如果您对此感兴趣,可以在此时获取其退出状态。

选项 (2( 需要处理更多细节 - 比上述概述可能暗示的更均匀。 如果需要,您会在SO上找到许多答案,可以解决这些问题。

您无法通过调用system()来完成此操作,因为它将在快速退出的新进程中完成。

但是,您可以调用setenv - 它将编辑当前正在运行的进程(您的C程序(的环境变量,并且它可能被您可能创建的所有进程继承,例如使用system()

像这样:

system("a = 2; echo $a");