【问题标题】:Redirect bash stdin and stdout in c++在 C++ 中重定向 bash 标准输入和标准输出
【发布时间】:2026-02-22 03:50:02
【问题描述】:

我需要帮助才能完成以下工作。我需要从 c++ 启动一个 bash 进程,这个 bash 进程需要接受来自 stdin 的输入并按照正常输出到 stdout。

我需要从不同的进程向标准输入写入命令,然后按照上面的方法在 bash 中实际执行,然后我对标准输出的结果感兴趣。

这是我迄今为止尝试过的,但输出对我来说根本没有意义......

        if (pipe(pipeBashShell)) {
            fprintf(stderr, "Pipe error!\n");
            exit(1);
        }

        if ((pipePId = fork()) == -1) {
            fprintf(stderr, "Fork error. Exiting.\n"); /* something went wrong */
            exit(1);
        }

        if (pipePId == 0) { //this is the child process
            dup2(pipeBashShell[0], STDIN_FILENO);
            dup2(pipeBashShell[1], STDOUT_FILENO);
            dup2(pipeBashShell[1], STDERR_FILENO);

            static char* bash[] = {"/bin/bash", "-i", NULL};
            if (execv(*bash, bash) == -1) {
                fprintf(stderr, "execv Error!");
                exit(1);
            }
            exit(0);
        } else {
            char buf[512];
            memset(buf, 0x00, sizeof(buf));
            sprintf(buf, "ls\n");
            int byteswritten = write(pipeBashShell[1], buf, strlen(buf));
            int bytesRead = read(pipeBashShell[0], buf, sizeof(buf));

            write(STDOUT_FILENO, buf, strlen(buf));
            exit(0);
        }

.

上面的结果输出如下:

'(主要) bash:: 找不到命令 gerhard@gerhard-work-pc:~/workspaces/si/si$ gerhard orkspaces/si/si$ gerhard@gerhard-work-pc:~/workspa ....

我试图发送到 bash 的命令是“ls”,它应该给我一个目录列表

我错过了什么吗?

【问题讨论】:

    标签: c++ bash redirect stdout stdin


    【解决方案1】:

    您已经创建了 一个 管道(有两端),并且您正尝试将其用于双向通信——从主进程到 bash,反之亦然。为此,您需要两个单独的管道。

    您连接文件描述符的方式使 bash 与自身对话——它将提示解释为它无法找到的命令,然后将错误消息解释为后续命令。

    编辑:

    正确的设置如下:

    1. 准备两个管道:

      int parent2child[2], child2parent[2];
      pipe(parent2child);
      pipe(child2parent);
      
    2. fork()

    3. 在父进程中:

      close(parent2child[0]);
      close(child2parent[1]);
      // write to parent2child[1], read from child2parent[0]
      
    4. 在子进程中:

      close(parent2child[1]);
      close(child2parent[0]);
      dup2(parent2child[0], STDIN_FILENO);
      dup2(child2parent[1], STDOUT_FILENO);
      

    【讨论】:

    • @GrzergorzHerman 如果你有一些文档/手册页从中提取了这个,你能用这个编辑你的答案吗,我将不胜感激,我也在研究这个
    • @KGCybeX,man 2 pipe 的描述部分开头声明它是一个单向通信通道,同一页面包含一个单向通信示例; man 2 dup 解释文件描述符的洗牌;其余部分从逻辑上遵循我们要写入/读取的孩子的 stdin/out/err。