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

问题描述 投票:4回答:3

给出以下答案(第一个c ++ 11答案):

How to execute a command and get output of command within C++ using POSIX?

以下是为方便起见的实施方案:

#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>

std::string exec(const char* cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
    if (!pipe) throw std::runtime_error("popen() failed!");
    while (!feof(pipe.get())) {
        if (fgets(buffer.data(), 128, pipe.get()) != nullptr)
            result += buffer.data();
    }
    return result;
}

这非常适合执行命令(例如std::string res = exec("ls");)并将stdout转换为字符串。

但它没有做的是获取命令返回码(通过/失败整数)或stderr。理想情况下,我想要一种方法来获取所有三个(返回代码,stdout,stderr)。

我会满足于stdout和stderr。我想我需要添加另一个管道,但是我无法真正看到第一个管道是如何设置来获得stdout所以我无法想象我将如何更改它以获得两者。

任何人都有任何想法如何做到这一点,或可能有效的替代方法?

更新

请参阅我的完整示例qazxsw poi输出:

here

您可以看到Start 1 res: /home 2 res: stdout stderr 3 res: End 不会像3 res:那样打印stderr,但是stderr只是通过进程(而不是我的程序)在单独的行上转储到屏幕上。

外部自由人

我真的不想使用像Qt和boost这样的外部库 - 主要是因为我想要它的可移植性以及我工作的许多项目都不使用boost。但是我会标记包含这些选项的解决方案,因为它们对其他用户有效:)

完整解决方案使用评论/答案

感谢所有人的回答/评论,这里是修改后的解决方案(和runnable):

2 res: stdout

c++ c++11 process stdout stderr
3个回答
7
投票

working-solution的手册页:

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<>

使用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; } 获取stderr和stdout,我担心你需要通过添加popen()将stderr的输出从你传递给popen()的命令行重定向到stdout。这令人不安,两种流都是不可预测的混合。

如果你真的想要为stderr和stdout提供两个不同的文件描述符,一种方法是自己进行分叉并将新进程stdout / stderr复制到两个可从父进程访问的管道。 (见2>&1dup2())。我可以在这里详细介绍,但这是一种相当繁琐的做事方式,必须非常小心。互联网上充满了例子。


3
投票

有一种可行的解决方法。您可以通过在cmd中附加“2>&1”将stderr重定向到stdout。这会满足你的需求吗?


1
投票

您可以使用自定义删除器从管道获取返回代码:

pipe()
© www.soinside.com 2019 - 2024. All rights reserved.