从 c++ 中的实例化进程获取输出的可靠方法是什么?
What is a reliable way to get output from instantiated processes in c++?
基本上我想做的是在Linux shell中实例化一个程序,并将它发出的输出获取到标准输出到字符串或字符串列表中(每行,取决于(。我想在我的c ++应用程序中运行的程序只是一个ps aux
。
- 找到的所有"解决方案"都没有完全解决我的问题。他们中的大多数都属于本答案中描述的错误。基本上
popen
失败,并且不会返回 shell 执行的完整输出。为了这个问题,我们称之为"错误 1"。
到目前为止我尝试过:
1(使用boost,我按照他们的文档尝试了这个:
#include <boost/process.hpp>
namespace bp = boost::process;
bool is_process_running(std::string p_name){
string cmd = "ps aux";
bp::ipstream out;
std::string line;
bp::child c(cmd, bp::std_out > out);
// the while is supposed to read each line of the output
// but the execution doesn't even enter the while
while(c.running() && std::getline(out, line) && !line.empty())
{
if(line.find(p_name) != std::string::npos)
{
return true;
}
}
c.wait();
return false;
}
2(我也尝试过:
bool is_process_running(std::string p_name){
string cmd = "ps aux";
std::array<char, 256> buffer;
std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
if (!pipe) throw std::runtime_error("popen() failed!");
while (!feof(pipe.get())) {
if (fgets(buffer.data(), 256, pipe.get()) != nullptr)
{
// here the line comes incomplete
std::string line(buffer.data());
if(line.find(p_name) != std::string::npos)
{
return true;
}
}
}
return false;
}
但最后一个也陷入了"错误1"。
3(这个代码片段落入"错误1">
4(这个也落入"错误1"
我不这样做,有必要输入 3( 和 4( 的代码,因为它实际上是这些答案中的内容,我没有更改任何东西,但如果你们需要,我可以编辑我的问题。所以我的问题就是这个,如何以一种可行的方式获取命令输出?提前谢谢。
编辑: 我已经尝试使用提供的代码截取
:bool is_process_running(std::string p_name)
FILE* p = popen(cmd.c_str(), "r");
if (!p) { cerr << "oops"; return 2; }
char line[500];
while (fgets(line, 500, p))
{
std::string linha(line);
if(linha.find(p_name) != std::string::npos)
return true;
}
fclose(p);
return false;
}
在这种情况下,下面是 popen/fgets 截断输出的示例:
[fabio ~]$ ps aux | grep 391
root 391 0.0 0.1 48580 12864 ? Ss Sep03 0:06 /usr/lib/systemd/systemd-journald
fabio 15435 0.0 0.0 112548 960 pts/2 S+ 15:40 0:00 grep --color=auto 391
进程 391 的行与此行相同,但在运行时它只返回我"root 391 0.0 0.1 48580 12856 ? Ss Sep03 0:06 /usr/lib/systemn"
直接使用相关的系统调用:pipe(2(、fork(2(、dup2(2(、close(2(、execve(2(、waitpid(2(。阅读一些好的Linux编程书籍(也许是旧的ALP,其中有几个章节与您的问题相关(。在处理管道的其他自由软件程序的源代码中寻找灵感(例如,一些简单的shell,如sash
(和/或libc
(或musl-libc,它具有非常可读的代码(以获取popen
代码。
我们没有空间和时间来详细解释,但你会在网上找到很多资源,ALP是可以免费下载的;当然execve
是通常在子进程中运行的最后一个系统调用,因为它正在重新初始化虚拟地址空间。
在不限制线长度的情况下从管道读取。要么手动使用 read(2( (并关心缓冲(,要么考虑 getline(3( (另请参阅 fdopen(3((
您可能对POCO或Qt等框架感兴趣。
你可能想避免使用 popen(3( (并且你不需要使用/bin/sh
的东西,除非你的命令需要扩展以进行通配; 参见 glob(7((。
注意信号(7(和信号安全(7((也许还有民意调查(2(...
我想在 c++ 应用程序中运行的程序只是一个
ps aux
那么你可能不应该运行任何外部进程,而是直接访问/proc/
(参见 proc(5(;你需要 opendir(3(、readdir(3( 等(,或者通过一些libproc
。当然,ps aux
是访问/proc/
本身(因此,除了运行ps
的一些简单性之外,您不会获得任何东西,并且使用它会失去一些性能和一些健壮性(。另请参阅这个,这个,这个,这个,这个答案。
在您提到的评论中
我需要知道某些进程是否在给定其名称和参数的情况下正在运行。
这是以编程方式访问/proc/
的一个很好的例子:使用opendir
循环/proc/
目录,循环readdir
、enddir
。对于readdir
给出的每个条目,请检查它是否具有数字名称(以数字开头(,否则跳过它。使用该数字名称(例如1234
(构造一个类似/proc/1234/cmdline
的路径并打开它,然后解析其内容(它具有分隔的NUL字节(。这可能并不比启动ps aux
过程、获取和解析其输出更难,而且肯定更有效。(要了解详细信息,请运行od -cx /proc/self/cmdline
然后od -cx /proc/$(pidof systemd-journald)/cmdline
并了解其输出(。
- 通过构造函数方法输出的类到类类型转换是 5500 为什么不是 5555
- 从 c++ 中的实例化进程获取输出的可靠方法是什么?
- is_permutation方法从 #include<algorithm> 显示错误的输出
- 将多个效果与 libSox 链接并读取输出数据的正确方法
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- 如何使用方法覆盖在输出屏幕上显示堆栈整数值
- 有没有一种简单的方法可以将矢量 int 集转换为字符串输出?
- 使控制台输出是否"verbose"的最快方法
- 如何优雅地实现具有可变输出的单个方法?
- 我试着了解方法覆盖是如何工作的,不知道为什么输出 2
- 快速获取C Eclipse中图形输出的方法
- 为什么我没有使用班级的tostring方法获得输出
- 将QProcess输出发送到TextEdit的最佳方法
- 在不同于依赖DLL的文件夹中输出已编译目标的正确方法是什么
- 有没有一种简单的方法可以将系统命令的输出转换为字符串
- 如何在c++中将方法的cout输出输出到流文件中
- 与参数同名的方法会导致不同的输出
- 当输出参数是类时,如何在C++中调用COM方法
- 使用 COUT 的 C++ 静态方法输出始终为 1
- 将文件的全部内容读取到标准输出的最短方法是什么