在Linux中使用C语言通过管道获取命令输出

3
我需要运行一个 Linux 命令并从 C 语言中获取其 stdout 输出。
我可以使用 pipe() 创建一个管道,然后进行 fork/exec,在调用 exec() 之前将子进程的 stdout 描述符重定向到管道中,并在父进程中从管道中读取。此外,我还需要等待子进程完成。
是否有一种简单的调用方式来执行 fork + 重定向 + exec + 等待,就像 system() 执行 fork + exec + wait 一样,只是 system() 不进行重定向。
有 popen() 函数,它执行 fork + 重定向 + exec,但不进行等待,所以无法获取退出状态。
4个回答

6

这是它吗?

名称
       popen,pclose - 进程I/O
语法 #include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
描述 popen()函数通过创建管道、分叉和调用shell来打开进程。由于管道在定义上是单向的,因此类型参数只能指定读取或写入,而不能同时;相应的流相应地为只读或只写。
命令参数是一个指向包含shell命令行的空终止字符串的指针。使用-c标志将此命令传递给/bin/sh;如果有,则由shell执行解释。类型参数是一个指向必须为“r”(读取)或“w”(写入)的空终止字符串的指针。
popen()的返回值在所有方面都是正常的标准I/O流,除了它必须使用pclose()而不是fclose()关闭。向这样的流写入会写入命令的标准输入;命令的标准输出与调用popen()的进程的标准输出相同,除非命令本身改变了这一点。反之,从“popened”流中读取会读取命令的标准输出,并且命令的标准输入与调用popen()的进程的标准输入相同。
请注意,默认情况下,输出popen()流是完全缓冲的。
pclose()函数等待关联的进程终止,并返回由wait4()返回的命令的退出状态。

2
pclose() 带有一个警告:无法执行 shell 与 shell 无法执行命令或立即退出命令的失败是无法区分的。唯一的提示是退出状态为 127。因此,如果这不足够,您必须像 dmckee 所说的那样编写自己的代码。 - Vinko Vrsalovic

3
GLib有一个非常好用的函数可以实现此功能 --g_spawn_sync()http://library.gnome.org/devel/glib/stable/glib-Spawning-Processes.html#g-spawn-sync 例如,要运行一个命令并获取其退出状态和输出:
const char *argv[] = { "your_command", NULL };
char *output = NULL; // will contain command output
GError *error = NULL;
int exit_status = 0;
if (!g_spawn_sync(NULL, argv, NULL, 0, NULL, NULL, 
                  &output, NULL, &exit_status, &error))
{
  // handle error here
}

1

这是我使用的:

   /* simply invoke a app, pipe output*/
    pipe = popen(buf, "r" );
    if (pipe == NULL ) {
        printf("invoking %s failed: %s\n", buf, strerror(errno));
        return 1;
    }

    waitfor(10);

    while(!feof(pipe) ) {
        if( fgets( buf, 128, pipe ) != NULL ) {
            printf("%s\n", buf );
        }
    }

    /* Close pipe */
    rc = pclose(pipe);

1
使用 popen()pclose()

popen()并不会真正等待,但是管道上的读取将会阻塞,直到有数据可用。

pclose()会等待,但是过早地调用它可能会中断分叉进程的一些输出。您需要从流中确定子进程何时完成...


可能已经在如何从C中运行外部程序并解析其输出?上讨论过。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接