Basically what I want to do is to instantiate a program in a Linux shell and get the outputs that it emits to stdout into a string or list of strings (per line, depending). The program I want to run in my c++ application is just a ps aux
.
- All the "solutions" I've found didn't completely solved my problem. Most of them fell under the error described in this answer. Basically
popen
fails and doesn't return the complete output from the shell execution. Let's call this "error 1" for the sake of this question.
What I've tried so far:
1) Using boost, I tried this following their 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) I also tried:
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;
}
But this last one also fell into "error 1".
3) This code snippet fell into the "error 1"
4) This one also fell into "error 1"
I don't this it is necessary to put the codes for 3) and 4) because it is literally what is in these answers, I didn't change anything, but if you guys need I can edit my question. So my question is just this, how to get the command output in a way that will work? Thanks in advance.
Edit: I've tried with the code snipped provided:
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;
}
In this case, here is an example of the truncated output from 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
The line for the process 391 is as this one but at runtime it only returns me "root 391 0.0 0.1 48580 12856 ? Ss Sep03 0:06 /usr/lib/system\n"