标准错误和popen():怎么做?

时间:2010-10-14 14:19:18

标签: c unix posix popen

我想从C代码中打开一个进程,并能够读取其标准输出和标准错误,同时能够写入其标准输入。

我最接近实现此目的是使用popen(),但这不允许您读取标准错误流。您可以在命令中添加“2>&1”,但这样就无法区分标准输出和错误数据。我的应用程序需要能够分离两个流。

Python有popen3而Ruby有Open3来做这些事情,但我似乎无法在C中找到办法。任何帮助?

3 个答案:

答案 0 :(得分:4)

#include <unistd.h>
#include <stdio.h>

...


int pipe_err[2], pipe_out[2], pipe_in[2];

if (pipe(pipe_err) || pipe(pipe_out) || pipe(pipe_in)) { // abbreviated error detection
     perror("pipe");
     scream_and_run_around_frantically();
     exit(BAD);
}
pid_t pid = fork();
if (!pid) { // in child
    dup2(pipe_err[1], 2);
    dup2(pipe_out[1], 1);
    dup2(pipe_in[0], 0);
    close(pipe_err[0]);
    close(pipe_err[1]);
    close(pipe_out[0]);
    close(pipe_out[1]);
    close(pipe_in[0]);
    close(pipe_in[1]);

    // close any other files that you don't want the new program
    // to get access to here unless you know that they have the
    // O_CLOEXE bit set

    execl(program_path, program_name, arg1, arg2, arg3);
    /* only gets here if there is an error executing the program */
 } else { // in the parent
     if (pid < 0) {
           perror("fork");
           error_death_plague_stubbed_toe();
           exit(BAD);
     }
     child_err = pipe_err[0];
     close(pipe_err[1]);
     child_out = pipe_out[0];
     close(pipe_out[1]);
     child_in = pipe_in[1];
     close(pipe_in[0]);

     ...

你可能想看看

man 3 exec

这有很多功能可以将当前程序转换为新程序。它们都有不同的界面,但在底层使用execve

man 2 execve

此外:

man 2 fork

man 2 pipe

答案 1 :(得分:2)

您可能需要考虑使用execl()。这是popen()内部使用的内容。

答案 2 :(得分:1)

如果您正在分配子进程,则可以复制stderr的句柄并在子进程中使用它。