且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在C++中执行命令并获取命令的返回码stdout和stderr

更新时间:2022-06-15 06:01:28

来自 popen 的手册页:

The pclose() function waits for the associated process to terminate  and returns the exit status of the command as returned by wait4(2).

因此,自己调用 pclose()(而不是使用 std::shared_ptr<> 的析构函数魔术)将为您提供进程的返回码(如果进程未终止,则阻塞).

So, calling pclose() yourself (instead of using std::shared_ptr<>'s destructor-magic) will give you the return code of your process (or block if the process has not terminated).

std::string exec(const char* cmd) {
    std::array<char, 128> buffer;
    std::string result;

    auto pipe = popen(cmd, "r"); // get rid of shared_ptr

    if (!pipe) throw std::runtime_error("popen() failed!");

    while (!feof(pipe)) {
        if (fgets(buffer.data(), 128, pipe) != nullptr)
            result += buffer.data();
    }

    auto rc = pclose(pipe);

    if (rc == EXIT_SUCCESS) { // == 0

    } else if (rc == EXIT_FAILURE) {  // EXIT_FAILURE is not used by all programs, maybe needs some adaptation.

    }
    return result;
}

使用 popen() 获取 stderr 和 stdout,恐怕您需要通过添加将 stderr 的输出从传递给 popen() 的命令行重定向到 stdout2>&1.这带来了两个流不可预测地混合的不便.

Getting stderr and stdout with popen(), I'm afraid you'd need to redirect the output of stderr to stdout from the command-line you're passing to popen() by adding 2>&1. This has the inconvinience that both streams are unpredictably mixed.

如果您真的想要为 stderr 和 stdout 拥有两个不同的文件描述符,一种方法是自己进行分叉并将新进程 stdout/stderr 复制到可从父进程访问的两个管道中.(参见 dup2()pipe()).我可以在这里详细介绍,但这是一种相当乏味的做事方式,必须非常小心.互联网上到处都是例子.

If you really want to have two distinguished file-descriptors for stderr and stdout, one way to do it is to do the forking yourself and to duplicate the new processes stdout/stderr to two pipes which are accessible from the parent process. (see dup2() and pipe()). I could go into more detail here, but this is quite a tedious way of doing things and much care must be taken. And the internet is full of examples.