popen() writes output of command executed to cout

31,093

Solution 1

Popen doesn't capture stderr only stdout. Redirecting stderr to stdout fixes the issue.

#include <string>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <array>

int main()
{
    std::string command("ls afskfksakfafkas 2>&1");

    std::array<char, 128> buffer;
    std::string result;

    std::cout << "Opening reading pipe" << std::endl;
    FILE* pipe = popen(command.c_str(), "r");
    if (!pipe)
    {
        std::cerr << "Couldn't start command." << std::endl;
        return 0;
    }
    while (fgets(buffer.data(), 128, pipe) != NULL) {
        std::cout << "Reading..." << std::endl;
        result += buffer.data();
    }
    auto returnCode = pclose(pipe);

    std::cout << result << std::endl;
    std::cout << returnCode << std::endl;

    return 0;
}

Solution 2

You have to add "2>&1" at the end of command string

command.append(" 2>&1");

there is a full example https://www.jeremymorgan.com/tutorials/c-programming/how-to-capture-the-output-of-a-linux-command-in-c/

Share:
31,093
John Smith
Author by

John Smith

Updated on October 12, 2021

Comments

  • John Smith
    John Smith over 2 years

    I am writing an application that needs to open another process and get its output. Everywhere I've read online says I have to use popen and read from the file.

    But I can't read from it. The output of the command gets outputted into the console window of the calling application. Below is the code I am using. I added some prints to debug.

    #include <string>
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <array>
    
    int main()
    {
        // some command that fails to execute properly.
        std::string command("ls afskfksakfafkas");
    
        std::array<char, 128> buffer;
        std::string result;
    
        std::cout << "Opening reading pipe" << std::endl;
        FILE* pipe = popen(command.c_str(), "r");
        if (!pipe)
        {
            std::cerr << "Couldn't start command." << std::endl;
            return 0;
        }
        while (fgets(buffer.data(), 128, pipe) != NULL) {
            std::cout << "Reading..." << std::endl;
            result += buffer.data();
        }
        auto returnCode = pclose(pipe);
    
        std::cout << result << std::endl;
        std::cout << returnCode << std::endl;
    
        return 0;
    }
    

    Reading is never actually printed to my cout and result is an empty string. I clearly see the output of the command in my terminal. If the command exits gracefully the behaviour is as expected. But I only capture the output for error cases.

    • Peter
      Peter almost 7 years
      Using feof() to control a loop is bad practice, and is pointless in your case since fgets() returns NULL on end of file. Try providing an minimal reproducible example that people can use to recreate your problem. If you don't know what the problem is, then providing partial information like you have is a good way to leave out critical information. It is quite possible the command you are running is using a means of output that isn't redirectable using your technique.
    • John Smith
      John Smith almost 7 years
      @Peter Provided full example. I literally just added int main and added a hardcoded command...