基本上我想要做的是在Linux shell中实例化一个程序,并将它发出的输出到stdout到字符串或字符串列表中(每行,取决于)。我想在我的c ++应用程序中运行的程序只是一个ps aux
。
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
等一些简单的shell)和/或libc
代码中的musl-libc(或popen
,它具有非常易读的代码)。
我们没有足够的空间和时间来详细解释,但您可以在Web上找到许多资源,ALP可以免费下载;当然,execve
是最后一次在子进程中运行的系统调用,因为它正在重新初始化虚拟地址空间。
从管道读取而不限制线路长度。要么手动使用read(2)(并关心缓冲),要么考虑getline(3)(另见fdopen(3))
你可能想要避免popen(3)(你不需要使用/bin/sh
的东西,除非你的命令需要扩展为globbing;参见glob(7))。
注意signal(7)和signal-safety(7)(也许poll(2) ......)
我想在我的c ++应用程序中运行的程序只是一个
ps aux
然后你可能应该not运行任何外部过程,但直接访问/proc/
(请参阅proc(5);你需要opendir(3),readdir(3)等...)或者可能通过一些libproc
。当然ps aux
本身正在访问/proc/
(因此除了通过运行ps
的一些简单性之外你不会获得任何东西,并且通过使用它会失去一些性能和一些稳健性)。另见this,this,this,this,this答案。
在你提到的评论中
我需要知道某些进程是否正在运行,同时给出它的名称和参数。
这是以编程方式访问/proc/
的一个很好的例子:使用/proc/
循环opendir
目录,循环readdir
,enddir
。对于readdir
给出的每个条目,检查它是否有数字名称(以数字开头),否则跳过它。使用该数字名称(例如1234
)构造一个像/proc/1234/cmdline
和open it then parse its content(它已经分离NUL字节)的路径。这可能不比启动ps aux
进程,获取和解析其输出更难,并且肯定更有效。 (要了解细节,请运行od -cx /proc/self/cmdline
然后od -cx /proc/$(pidof systemd-journald)/cmdline
并了解其输出)。