如何捕获 execvp 的输出

Posted

技术标签:

【中文标题】如何捕获 execvp 的输出【英文标题】:How to capture output of execvp 【发布时间】:2009-04-17 21:04:42 【问题描述】:

我正在开发一个使用 execvp 执行程序的程序。它需要捕获子进程的结果并在主进程中解析它们。似乎有一种方法,使用命名管道和复制。我正在努力寻找一个很好的例子,但到目前为止还没有运气。如果有人对此有任何指示、链接和/或建议,我将不胜感激。

【问题讨论】:

相关:get command output in pipe, C for Linux 【参考方案1】:

你不需要命名管道;未命名的管道工作得很好。实际上,您通常可以只使用popen 而不是自己使用pipe/fork/dup/execpopen 是这样工作的(尽管你的 libc 的实现可能有更多的错误检查):

FILE *popen(const char *command, const char *type) 
    int fds[2];
    const char *argv[4] = "/bin/sh", "-c", command;
    pipe(fds);
    if (fork() == 0) 
        close(fds[0]);
        dup2(type[0] == 'r' ? 0 : 1, fds[1]);
        close(fds[1]);
        execvp(argv[0], argv);
        exit(-1);
    
    close(fds[1]);
    return fdopen(fds[0], type);

这将创建一个未命名的管道和forks。在孩子中,它将标准输出(或标准输入)重新附加到管道的一端,然后execs 孩子。父级可以简单地从管道的另一端读取(或写入)。

【讨论】:

太棒了。我已经回顾了管道的工作原理,这应该可以解决问题。 如果有人偶然发现这一点,仅供记录。基于 type[0] 的条件并不完全正确。需要在 dup2 之前关闭 stdout/stdin 才可能。此外,管道是单向的,fds[1] 是写入端,因此它需要是 dup2 中的 fds[0] 用于读取情况。 @TommiKyntola 来自dup2 手册页:“使newfd 成为oldfd 的副本,如有必要,首先关闭newfd”所以这应该有效无需先手动关闭 stdout/stdin。【参考方案2】:

你不能只使用 popen() 吗?

【讨论】:

【参考方案3】:

这是一个简单的例子,演示如何使用 popen 来实现您的目标。只需将比“echo”更有趣的东西作为命令:)

#include <stdio.h>

int main() 

    char buf[100];
    int i = 0;
    FILE *p = popen("echo \"Test\"","r");
    if (p != NULL )
    
        while (!feof(p) && (i < 99) )
        
            fread(&buf[i++],1,1,p);
        
        buf[i] = 0;
        printf("%s",buf);
        pclose(p);
        return 0;
    
    else
    
        return -1;
    

【讨论】:

以上是关于如何捕获 execvp 的输出的主要内容,如果未能解决你的问题,请参考以下文章

允许使用execvp执行程序

如何在 Windows 上有效地“替换”`os.execvpe` - 如果“子”进程是交互式命令行应用程序?

execvp() 永远不会在管道上完成

pthread 的 malloc 内存,然后 fork + execvp

linux进程---exec族函数(execl, execlp, execle, execv, execvp, execvpe)

制作:execvp:g ++:权限被拒绝