如何在C ++中执行命令并获取命令的返回码stdout和stderr [英] How to execute a command and get return code stdout and stderr of command in C++
问题描述
给出以下答案(第一个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屋!