如何在C ++中执行命令并获取命令的返回码stdout和stderr [英] How to execute a command and get return code stdout and stderr of command in C++

查看:238
本文介绍了如何在C ++中执行命令并获取命令的返回码stdout和stderr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Given the following answer (first c++11 answer):

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

以下是为您方便起见的实现:

Here is the implementation for your convinience:

#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转换为字符串。

This works really nicely to execute a command (e.g. std::string res = exec("ls");) and get the stdout into a string.

但是它不能做什么获取命令返回码(通过/失败整数)或stderr。理想情况下,我希望获得所有这三个代码(返回码,stdout,stderr)。

But what it does not do is get the command return code (pass/fail integer) or the stderr. Ideally I would like a way to get all three (return code, stdout, stderr).

我会选择stdout和stderr。我在想我需要添加另一个管道,但是我真的看不到如何设置第一个管道以获取stdout,因此我无法考虑如何对其进行更改以同时获得这两个管道。

I would settle for stdout and stderr. I am thinking that I need to add another pipe, but I can't really see how the first pipe is setup to get stdout so I can't think how I would change it to get both.

任何人都知道如何执行此操作,或者可能有其他可行的方法?

Any one got any ideas how to do that, or alternative approaches that may work?

更新

请参阅我的完整示例此处,并带有输出:

See my complete example here witht the output:

Start
1 res: /home

2 res: stdout

stderr
3 res: 
End

您可以看到 3 res:不会以与 2 res:stdout 相同的方式打印stderr,但是stderr只是转储到屏幕上

You can see that 3 res: does not print stderr in the same way that 2 res: stdout does, but stderr is just dumped onto the screen on a seperate line by the process (and not my program).

外部库

我真的不想使用诸如Qt和boost之类的外部库-主要是因为我想要它的可移植性以及我所从事的许多项目ork on不要使用boost。但是,我将标记包含这些选项的解决方案,因为它们对于其他用户有效:)

I really don't want to use external libraries like Qt and boost - mostly because I want the portability of it and also many projects that I work on don't use boost. However I will mark up solutions that contain these options as they are valid for other users :)

使用注释/答案完成解决方案

感谢您的回答/评论,以下是修改后的解决方案(可运行):

Thanks all for your answers / comments, here is the modified solution (and runable):

工作解决方案

推荐答案

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<> 的destructor-magic可以为您提供流程的返回代码(如果流程尚未终止,则返回代码)。 / p>

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 ,恐怕您需要通过将 2>& 1 从传递给popen()的命令行中将stderr的输出重定向到stdout。 code>。

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.

这篇关于如何在C ++中执行命令并获取命令的返回码stdout和stderr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆