给出以下答案(第一个 c++11 答案):
如何使用 POSIX 在 C++ 中执行命令并获取命令的输出?
为了您的方便,这里是实现:
#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");
)并将标准输出转换为字符串。
但它不做的是获取命令返回码(通过/失败整数)或标准错误。理想情况下,我想要一种方法来获取所有三个(返回代码、标准输出、标准错误)。
我会满足于标准输出和标准错误。我在想我需要添加另一个管道,但是我真的看不到第一个管道是如何设置来获取标准输出的,所以我想不出如何改变它来获取两者。
任何人有任何想法如何做到这一点,或者可能有效的替代方法?
更新
在这里 查看我的完整示例和输出:
Start
1 res: /home
2 res: stdout
stderr
3 res:
End
您可以看到 3 res:
不会以与 2 res: stdout
相同的方式打印 stderr ,但 stderr 只是由进程(而不是我的程序)在单独的行上转储到屏幕上.
外部库
我真的不想使用像 Qt 和 boost 这样的外部库——主要是因为我想要它的可移植性,而且我从事的许多项目也不使用 boost。但是,我将标记包含这些选项的解决方案,因为它们对其他用户有效:)
使用评论/答案的完整解决方案
感谢大家的回答/评论,这是修改后的解决方案(并且可运行):
原文由 code_fodder 发布,翻译遵循 CC BY-SA 4.0 许可协议
从
popen
的手册页中:因此,您自己调用
pclose()
(而不是使用std::shared_ptr<>
的析构函数)将为您提供进程的返回码(如果进程尚未终止,则阻止)。使用
popen()
获取标准错误和标准输出,恐怕您需要通过添加2>&1
从传递给 popen() 的命令行将标准错误的输出重定向到标准输出---
。这带来的不便之处在于两种流都不可预测地混合在一起。如果您真的想为 stderr 和 stdout 提供两个不同的文件描述符,一种方法是自己进行分叉并将新进程 stdout/stderr 复制到两个可从父进程访问的管道。 (参见
dup2()
和pipe()
)。我可以在这里更详细地介绍,但这是一种相当乏味的做事方式,必须非常小心。互联网上到处都是例子。