C++ system() function — How to collect the output of the issued command?
Are you looking for returned value (as in "exit status") of the executed command, or for its output (as in "what did it print")?
If the latter, use popen()
and pclose()
instead.
If the former, look at the return value from system()
(and use the documentation for waitpid()
to interpret it).
How do I execute a command and get the output of the command within C++ using POSIX?
#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::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
if (!pipe) {
throw std::runtime_error("popen() failed!");
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
return result;
}
Pre-C++11 version:
#include <iostream>
#include <stdexcept>
#include <stdio.h>
#include <string>
std::string exec(const char* cmd) {
char buffer[128];
std::string result = "";
FILE* pipe = popen(cmd, "r");
if (!pipe) throw std::runtime_error("popen() failed!");
try {
while (fgets(buffer, sizeof buffer, pipe) != NULL) {
result += buffer;
}
} catch (...) {
pclose(pipe);
throw;
}
pclose(pipe);
return result;
}
Replace popen
and pclose
with _popen
and _pclose
for Windows.
How to execute a command and get return code stdout and stderr of command in C++
From the man-page of popen
:
The pclose() function waits for the associated process to terminate and returns the exit status of the command as returned by wait4(2).
So, calling pclose()
yourself (instead of using std::shared_ptr<>
's destructor-magic) will give you the return code of your process (or block if the process has not terminated).
std::string exec(const char* cmd) {
std::array<char, 128> buffer;
std::string result;
auto pipe = popen(cmd, "r"); // get rid of shared_ptr
if (!pipe) throw std::runtime_error("popen() failed!");
while (!feof(pipe)) {
if (fgets(buffer.data(), buffer.size(), pipe) != nullptr)
result += buffer.data();
}
auto rc = pclose(pipe);
if (rc == EXIT_SUCCESS) { // == 0
} else if (rc == EXIT_FAILURE) { // EXIT_FAILURE is not used by all programs, maybe needs some adaptation.
}
return result;
}
Getting stderr and stdout with popen()
, I'm afraid you'd need to redirect the output of stderr to stdout from the command-line you're passing to popen() by adding 2>&1
. This has the inconvinience that both streams are unpredictably mixed.
If you really want to have two distinguished file-descriptors for stderr and stdout, one way to do it is to do the forking yourself and to duplicate the new processes stdout/stderr to two pipes which are accessible from the parent process. (see dup2()
and pipe()
). I could go into more detail here, but this is quite a tedious way of doing things and much care must be taken. And the internet is full of examples.
viewing output of system() call in C++
Use popen
instead of system
. See example here https://msdn.microsoft.com/en-us/library/96ayss4b.aspx
char psBuffer[128];
FILE *pPipe;
if( (pPipe = _popen( "set PATH=%PATH%;C:/Program Files (x86)/myFolder/bin", "rt" )) == NULL )
exit( 1 );
then
while(fgets(psBuffer, 128, pPipe)) {
printf(psBuffer);
}
if (feof( pPipe))
printf( "\nProcess returned %d\n", _pclose( pPipe ) );
An alternative way to get console output of system() function
As mentioned by @Charles Duffy, and @Kevin, system()
is not the function you want. popen()
is more suitable. The following should work. Please note, if you are using gcc
and compile with -std=c99
flag, you need to add #define _POSIX_C_SOURCE 2
before #include <stdio.h>
#include <stdio.h>
#include <error.h>
#define PATH_MAX 1024
int main(void)
{
FILE *fp;
int status;
char path[PATH_MAX];
fp = popen("iptables -t filter -L", "r");
if (fp == NULL)
{
perror("popen");
return -1;
}
while (fgets(path, PATH_MAX, fp) != NULL)
{
printf("%s", path);
/* do something you want with the return data */
}
status = pclose(fp);
if (status == -1)
{
perror("pclose");
}
return 0;
}
Related Topics
Ways to Detect Whether a C++ Virtual Function Has Been Redefined in a Derived Class
Why Is the Copy Constructor Called When We Pass an Object as an Argument by Value to a Method
How to Save Two Camera's Data But Not Influence Their Picture-Acquire Speed
Function Already Defined Error in C++
How to Safely Destruct a Qthread
How to Pass a Std::Function Object to a Function Taking a Function Pointer
Date/Time Conversion: String Representation to Time_T
Reading JSON File with C++ and Boost
Is It Ok Not to Call the Destructor on Placement New Allocated Objects
Narrowing Conversion from Unsigned to Double
What Does the Gcc Warning "Project Parameter Passing for X Changed in Gcc 7.1" Mean
Does New Line Character Also Flush the Buffer
What's the Difference Between Type(Myvar) and (Type)Myvar
C++11 Std::Mutex in Visual Studio 2012 Deadlock When Locked from Dllmain()