c++ - सिस्टम() कमांड से stdout को कैप्चर करना




system (7)

मैं system() माध्यम से बाहरी अनुप्रयोग शुरू करने की कोशिश कर रहा हूं - उदाहरण के लिए, system("ls") । मैं इसके आउटपुट को कैप्चर करना चाहता हूं क्योंकि ऐसा होता है इसलिए मैं आगे प्रसंस्करण के लिए इसे किसी अन्य फ़ंक्शन पर भेज सकता हूं। सी / सी ++ में ऐसा करने का सबसे अच्छा तरीका क्या है?


Popen () फ़ंक्शन का प्रयास करें। यह सिस्टम () की तरह एक कमांड निष्पादित करता है, लेकिन आउटपुट को एक नई फ़ाइल में निर्देशित करता है। धारा के लिए एक सूचक वापस आ गया है।

  FILE *lsofFile_p = popen("lsof", "r");

  if (!lsofFile_p)
  {
    return -1;
  }

  char buffer[1024];
  char *line_p = fgets(buffer, sizeof(buffer), lsofFile_p);
  pclose(lsofFile_p);

इस पृष्ठ में: capture_the_output_of_a_child_process_in_c फोर्क / exec / dup2 / STDOUT_FILENO दृष्टिकोण का उपयोग करके पॉपन बनाम उपयोग करने की सीमाओं का वर्णन करता है।

मुझे पॉपन के साथ tshark आउटपुट कैप्चर करने में समस्याएं आ रही हैं।

और मुझे लगता है कि यह सीमा मेरी समस्या हो सकती है:

यह कच्चे फ़ाइल डिस्क्रिप्टर के विपरीत एक स्टडीओ स्ट्रीम देता है, जो उत्पादन को असीमित रूप से संभालने के लिए अनुपयुक्त है।

अगर मैं दूसरे दृष्टिकोण के साथ समाधान करता हूं तो मैं इस जवाब पर वापस आऊंगा।


पॉपन मैनुअल से:

#include <stdio.h>

FILE *popen(const char *command, const char *type);

int pclose(FILE *stream);

फ़ंक्शन popen() और pclose() हो सकता है वह हो सकता है।

एक उदाहरण के लिए glibc मैनुअल पर एक नज़र डालें।


मैं पूरी तरह से निश्चित नहीं हूं कि मानक सी में यह संभव है, क्योंकि दो अलग-अलग प्रक्रियाएं आम तौर पर स्मृति स्थान साझा नहीं करती हैं। ऐसा करने का सबसे आसान तरीका यह है कि दूसरा प्रोग्राम अपने आउटपुट को टेक्स्ट फ़ाइल (प्रोग्रामनाम> textfile.txt) पर रीडायरेक्ट करना होगा और उसके बाद उस पाठ फ़ाइल को प्रोसेसिंग के लिए वापस पढ़ा जाएगा। हालांकि, यह सबसे अच्छा तरीका नहीं हो सकता है।


विंडोज़ में, सिस्टम () का उपयोग करने के बजाय, CreateProcess का उपयोग करें, आउटपुट को पाइप पर रीडायरेक्ट करें और पाइप से कनेक्ट करें।

मुझे लगता है कि कुछ पॉज़िक्स तरीके से यह भी संभव है?


FILE स्ट्रीम को छोड़कर सीधे stdout फ़ाइल डिस्क्रिप्टर का उपयोग करने का सबसे प्रभावी तरीका है:

pid_t popen2(const char *command, int * infp, int * outfp)
{
    int p_stdin[2], p_stdout[2];
    pid_t pid;

    if (pipe(p_stdin) == -1)
        return -1;

    if (pipe(p_stdout) == -1) {
        close(p_stdin[0]);
        close(p_stdin[1]);
        return -1;
    }

    pid = fork();

    if (pid < 0) {
        close(p_stdin[0]);
        close(p_stdin[1]);
        close(p_stdout[0]);
        close(p_stdout[1]);
        return pid;
    } else if (pid == 0) {
        close(p_stdin[1]);
        dup2(p_stdin[0], 0);
        close(p_stdout[0]);
        dup2(p_stdout[1], 1);
        dup2(::open("/dev/null", O_WRONLY), 2);

        /// Close all other descriptors for the safety sake.
        for (int i = 3; i < 4096; ++i) {
            ::close(i);
        }

        setsid();
        execl("/bin/sh", "sh", "-c", command, NULL);
        _exit(1);
    }

    close(p_stdin[0]);
    close(p_stdout[1]);

    if (infp == NULL) {
        close(p_stdin[1]);
    } else {
        *infp = p_stdin[1];
    }

    if (outfp == NULL) {
        close(p_stdout[0]);
    } else {
        *outfp = p_stdout[0];
    }

    return pid;
}

बच्चे के उपयोग से आउटपुट पढ़ने के लिए popen2() इस तरह:

int child_stdout = -1;
pid_t child_pid = popen2("ls", 0, &child_stdout);

if (!child_pid) {
    handle_error();
}

char buff[128];
ssize_t bytes_read = read(child_stdout, buff, sizeof(buff));

दोनों लिखने और पढ़ने के लिए:

int child_stdin = -1;
int child_stdout = -1;
pid_t child_pid = popen2("grep 123", &child_stdin, &child_stdout);

if (!child_pid) {
    handle_error();
}

const char text = "1\n2\n123\n3";
ssize_t bytes_written = write(child_stdin, text, sizeof(text) - 1);

char buff[128];
ssize_t bytes_read = read(child_stdout, buff, sizeof(buff));





stdout