【问题标题】:Capturing child stdout to a buffer将子标准输出捕获到缓冲区
【发布时间】:2014-02-13 01:12:23
【问题描述】:

我目前正在开发一个跨平台项目。在 Windows 上,我有一个运行进程/脚本(使用命令行)的类,等待它结束,然后从它的 stdout/stderr 读取所有内容到缓冲区。然后我将输出打印到自定义“控制台”。注意:这不是子标准输出到父标准输出的重定向,只是从子标准输出到父标准的管道。

我是 OSX/unix 类 api 的新手,但我可以理解做这种事情的规范方法是将标准输出分叉和管道在一起。但是,我不想将它重定向到标准输出,我想捕获输出。它应该像这样工作(伪代码,与 unix 函数的相似之处纯属巧合):

class program
{
    string name, cmdline;
    string output;
    program(char * name, char * cmdline)
        : name(name), cmdline(cmdline) {};

    int run()
    {
        // run program - spawn it as a new process
        int pid = exec(name, cmdline);
        // wait for it to finish
        wait(pid);
        char buf[size];
        int n;
        // read output of program's stdout
        // keep appending data until there's nothing left to read
        while (read(pid, buf, size, &n))
            output.append(buf, n);
        // return exit code of process
        return getexitcode(pid);
    }

    const string & getOutput() { return output;  }
};

我将如何在 OSX 上执行此操作?

E:

好的,所以我研究了相关的 api,似乎某种 fork/exec 组合是不可避免的。手头的问题是我的进程非常大并且分叉它看起来真的是个坏主意(我看到如果父进程占用系统的 50% 以上,一些 unix 实现就无法做到这一点内存)。

我不能以任何方式避免这种方案吗?我看到 vfork() 可能是一个可能的竞争者,所以也许我可以尝试使用 vfork 来模仿 popen() 函数。但是话又说回来,大多数手册页都指出 ​​vfork 很可能只是 fork()

【问题讨论】:

  • 也许它应该注意到它只是伪代码。 exec 应该执行命令行。

标签: c++ unix fork stdout child-process


【解决方案1】:

你有一个库调用来做到这一点:popen。它将为您提供文件描述符的返回值,您可以读取该描述符直到 eof。它是 stdio 的一部分,因此您可以在 OSX 上执行此操作,但也可以在其他系统上执行此操作。只要记住 pclose() 描述符。

 #include <stdio.h>

     FILE *     popen(const char *command, const char *mode);

     int    pclose(FILE *stream);

如果你想保持输出绝对没有重定向,我们唯一能想到的就是使用“tee”之类的东西——一个将输出拆分到文件但维护自己的标准输出的命令。在代码中实现它也相当容易,但在这种情况下可能没有必要。

【讨论】:

  • 这看起来很完美。两个问题,当我到达 EOF 时,我想这表明进程终止了?其次,Linux 手册页声明它是 fork 的包装器 - 这会对性能产生巨大影响(例如,我的代码位于一个巨大进程内的动态库中?)
  • 要在 UNIX 系统中创建进程,您必须使用 fork()/execv()(或 OS X 上的 posix_spawn,几乎相同)。但是不会对性能产生太大影响,除非你重复使用它数十次。至于 EOF,是的 - pclose() 也会等待进程结束,并返回它的返回值(即它退出()的内容)。
  • 好的,但这就是我要做的事情。这个想法当然是让主程序访问运行shell命令和程序,它有时会背靠背作为循环例程的一部分,可能是每分钟几次.. 我们可以假设主机进程消耗了大部分系统资源
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多