gpt4 book ai didi

c++ - 从 C++ 中的实例化进程获取输出的可靠方法是什么?

转载 作者:行者123 更新时间:2023-11-28 01:29:36 26 4
gpt4 key购买 nike

基本上我想做的是在 Linux shell 中实例化一个程序,并将它发出到标准输出的输出转换为字符串或字符串列表(每行,视情况而定)。我想在我的 C++ 应用程序中运行的程序只是一个 ps aux

  • 我找到的所有“解决方案”都没有完全解决我的问题。他们中的大多数都属于 this answer 中描述的错误。 .基本上 popen 失败并且不返回 shell 执行的完整输出。为了这个问题,我们称之为“错误 1”。

到目前为止我尝试了什么:

1) 使用 boost,我按照他们的 documentation 尝试了这个:

#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) This code snippet陷入“错误1”
4) This one也陷入了“错误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/system\n"

最佳答案

直接使用相关系统调用:pipe(2) , fork(2) , dup2(2) , close(2) , execve(2) , waitpid(2) .阅读一些不错的 Linux 编程书籍(可能是旧的 ALP,其中有几章与您的问题相关)。从其他处理管道的自由软件程序的源代码中寻找灵感(例如像 sash 这样的简单外壳)和/或在您的 libc(或 musl-libcpopen 的代码具有非常可读的代码)。

我们没有空间和时间来详细解释,但是您可以在 Web 上找到很多资源,而且 ALP 可以免费下载;当然 execve 是通常在子进程中运行的最后一个系统调用,因为它正在重新初始化虚拟地址空间。

在不限制行长度的情况下从管道读取。要么使用 read(2)手动(并关心缓冲),或考虑 getline(3) (另见 f dopen(3) )

您可能对 POCO 这样的框架感兴趣或 Qt .

你可能想避免 popen(3) (并且您不需要使用 /bin/sh 的东西,除非您的命令需要针对 globbing 进行扩展;请参阅 glob(7))。

注意 signal(7)signal-safety(7) (也许还有 poll(2) ...)


The program I want to run in my c++ application is just a ps aux

那么你可能应该not运行任何外部进程,而是访问 /proc/ 直接(参见 proc(5) ;您需要 opendir(3)readdir(3)等等...) 或者可能通过一些 libproc。当然 ps aux 正在访问 /proc/ 本身(所以你除了通过运行 ps 获得一些简单性之外什么也得不到,并且你失去了一些通过使用它的性能和一些健壮性)。另见 this , this , this , this , this答案。

在你提到的评论中

I need to know if some processes are running given both its name and arguments.

这是一个以编程方式访问 /proc/ 的好例子:使用 opendir/proc/ 目录上循环,循环 readdir enddir。对于 readdir 给出的每个条目,检查它是否具有数字名称(以数字开头),否则跳过它。使用该数字名称(例如 1234)构造一个路径,如 /proc/1234/cmdlineopen it then parse its content (它有分隔的 NUL 字节)。这可能并不比启动 ps aux 进程、获取和解析其输出更难,而且效率肯定更高。 (要了解详细信息,请运行 od -cx/proc/self/cmdline 然后运行 ​​od -cx/proc/$(pidof systemd-journald)/cmdline 并了解其输出) .

关于c++ - 从 C++ 中的实例化进程获取输出的可靠方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52191127/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com