আমি কীভাবে একটি কমান্ড কার্যকর করব এবং সি ++ এর মধ্যে পসিক্স ব্যবহার করে কমান্ডের আউটপুট পেতে পারি?


463

আমি যখন কোনও সি ++ প্রোগ্রামের মধ্যে থেকে চালানো হয় তখন কোনও কমান্ডের আউটপুট পাওয়ার উপায় খুঁজছি। আমি system()ফাংশনটি ব্যবহার করে দেখেছি , তবে এটি একটি কমান্ড কার্যকর করবে। আমি যা খুঁজছি তার একটি উদাহরণ এখানে:

std::string result = system("./some_command");

আমার একটি স্বেচ্ছাসেবক কমান্ড চালানো এবং এটির ফলাফল পাওয়া দরকার need আমি বুস্ট.আরআর.জি দেখেছি , তবে আমার কাছে যা প্রয়োজন তা দেবে এমন কিছুই আমি পাই নি।


এছাড়াও এই প্রশ্নের উত্তর দেখুন: /programming/52164723/how-to-execute-a-command-and-get-return-code-stdout-and-stderr-of-command-in-cমহান উত্তর নীচে সেই পেতে পদ্ধতি প্রদান করে একটি এক্সটেনশন জন্য return codeএবং stderrসেইসাথে stdoutএই উত্তরটি ইতিমধ্যে ব্যাখ্যা করেছেন যে
code_fodder

2
@code_fodder তোমাদের লিঙ্ক তৈরি করতে পারেন stackoverflow.com/questions/52164723/...
জোনাস স্টেইন

উত্তর:


599
#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;
}

প্রাক-সি ++ 11 সংস্করণ:

#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;
}

প্রতিস্থাপন popenএবং pcloseসঙ্গে _popenএবং _pcloseWindows এর জন্য।


69
সচেতন থাকুন যে এটি কেবল স্টাডআউটকে দখল করবে এবং স্টাডারকে নয় ।
ক্যালাক্সি

14
এছাড়াও সচেতন থাকুন যে কোনও ব্যতিক্রম ঘটতে পারে result += bufferতাই পাইপটি সঠিকভাবে বন্ধ নাও হতে পারে।
ফ্রেড ফু

6
@ ইয়াস্কি: যখন প্রোগ্রামটি কার্যকর করা হয় int main(){ puts("ERROR"); }
ড্রিমলাক্স

8
উত্তরটি ভাল তবে আপনি যদি 'চর *
সেন্টিমিডি

29
অনন্য_পিটার এখানে আরও ভাল ফিট, যেখানে প্রকৃত রেফারেন্স গণনাটি কখনই ব্যবহৃত হয় না।
সিজিপার্জ

77

স্টাডাউট এবং স্টেডার উভয়ই পাওয়া (এবং এখানে স্ট্যান্ডিনে লেখাও নয়, এখানে দেখানো হয়নি) আমার প্রবাহের শিরোনামের সাথে সহজ প্যাসিটি , যা আইওস্ট্রিম ক্লাসগুলি যেমন কাজ করে তা সংজ্ঞায়িত করে popen:

#include <pstream.h>
#include <string>
#include <iostream>

int main()
{
  // run a process and create a streambuf that reads its stdout and stderr
  redi::ipstream proc("./some_command", redi::pstreams::pstdout | redi::pstreams::pstderr);
  std::string line;
  // read child's stdout
  while (std::getline(proc.out(), line))
    std::cout << "stdout: " << line << '\n';
  # if reading stdout stopped at EOF then reset the state:
  if (proc.eof() && proc.fail())
    proc.clear();
  // read child's stderr
  while (std::getline(proc.err(), line))
    std::cout << "stderr: " << line << '\n';
} 

18
আমি একমত নই popenআপনি সি stdio এপিআই ব্যবহার করা প্রয়োজন, আমি iostreams API পছন্দ। popenআপনাকে ম্যানুয়ালি FILEহ্যান্ডেলটি পরিষ্কার করতে হবে , স্ট্রিমগুলি স্বয়ংক্রিয়ভাবে এটি করে। popenকেবল const char*যুক্তিটির জন্য একটি গ্রহণ করে , যার মধ্যে শেল ইঞ্জেকশন আক্রমণগুলি এড়াতে যত্নের প্রয়োজন হয়, প্রবাহগুলি আপনাকে অনুরূপ স্ট্রিংগুলির একটি ভেক্টরকে পাস করতে দেয় execvযা নিরাপদ। popenআপনাকে একটি পাইপ ব্যতীত আর কিছুই দেয় না, প্রবাহগুলি আপনাকে সন্তানের পিআইডি বলে দেয় যেমন আপনাকে সিগন্যাল প্রেরণ করতে মঞ্জুর করে eg আপনি কেবল একমুখী আইও চাইলেও এই সমস্তগুলির সুবিধা।
জোনাথন ওয়েকলি

1
এই সমাধানের সাথে অন্য একটি সমস্যাটি হল যদি শিশু স্টাফার লিখতে শুরু করার আগে বাফারগুলিকে পূরণ করার জন্য পর্যাপ্ত পরিমাণে স্টারডারকে লিখে এবং ব্লক করে। পিতা-মাতা স্টাডাউট পড়া বন্ধ করবে, যখন বাচ্চা স্টাডার পড়ার অপেক্ষায় অবরুদ্ধ। রিসোর্স অচল! এই লুপগুলির মধ্যে অন্তত একটি অ্যাসিনক্রোনাস (যেমন, থ্রেডেড) হিসাবে ভাল।
জেসি চিশল্ম

1
@ জেসি চিসলম, হ্যাঁ, এটি একটি সমস্যা হতে পারে। তবে আপনার থ্রেডগুলি ব্যবহার করার দরকার নেই কারণ প্লে স্ট্রিমগুলি আইওস্ট্রিম ইন্টারফেস ব্যবহার করে বিশেষত রিডোম ফাংশনটি ব্যবহার করে , যা ব্যবহারের জন্য তাত্পর্য পরীক্ষা করে pstreambuf::in_avail(), তাই ব্লক করবে না, এটি অ-ব্লকিং অ / ব্লকিংয়ের সমাপ্তির মঞ্জুরি দেয় । এটি প্রত্যেকের ডেটা উপলভ্য হওয়ার কারণে প্রক্রিয়াটির স্টাডআউট এবং স্টডারকে ডিলিটিপ্লিক্সিংয়ের অনুমতি দেয়। pstreambuf::in_avail()ওএস অ-মানক FIONREAD ioctl সমর্থন করে তবে 100% নির্ভরযোগ্যভাবে কাজ করে তবে এটি জিএনইউ / লিনাক্স এবং সোলারিসে সমর্থিত।
জোনাথন Wakely

13
@ chiliNUT নতুন 1.0.1 রিলিজ বুস্ট লাইসেন্স ব্যবহার করে।
জোনাথন ওয়াকলি

1
@ জোনাথন, কীভাবে আমি 5 সেকেন্ড টাইমআউট বলার পরে আইপস্ট্রিমটিকে হত্যা করতে পারি?
একে

34

আমি পপেন () (++ ওয়াকাস) ব্যবহার করব

তবে কখনও কখনও আপনার পড়া এবং লেখার প্রয়োজন হয় ...

দেখে মনে হচ্ছে কেউ আর শক্তভাবে কাজ করে না।

(ইউনিক্স / লিনাক্স / ম্যাক এনভায়রনমেন্ট, বা একটি পসিক্স সামঞ্জস্যতা স্তর সহ উইন্ডোজ সম্ভবত ...)

enum PIPE_FILE_DESCRIPTERS
{
  READ_FD  = 0,
  WRITE_FD = 1
};

enum CONSTANTS
{
  BUFFER_SIZE = 100
};

int
main()
{
  int       parentToChild[2];
  int       childToParent[2];
  pid_t     pid;
  string    dataReadFromChild;
  char      buffer[BUFFER_SIZE + 1];
  ssize_t   readResult;
  int       status;

  ASSERT_IS(0, pipe(parentToChild));
  ASSERT_IS(0, pipe(childToParent));

  switch (pid = fork())
  {
    case -1:
      FAIL("Fork failed");
      exit(-1);

    case 0: /* Child */
      ASSERT_NOT(-1, dup2(parentToChild[READ_FD], STDIN_FILENO));
      ASSERT_NOT(-1, dup2(childToParent[WRITE_FD], STDOUT_FILENO));
      ASSERT_NOT(-1, dup2(childToParent[WRITE_FD], STDERR_FILENO));
      ASSERT_IS(0, close(parentToChild [WRITE_FD]));
      ASSERT_IS(0, close(childToParent [READ_FD]));

      /*     file, arg0, arg1,  arg2 */
      execlp("ls", "ls", "-al", "--color");

      FAIL("This line should never be reached!!!");
      exit(-1);

    default: /* Parent */
      cout << "Child " << pid << " process running..." << endl;

      ASSERT_IS(0, close(parentToChild [READ_FD]));
      ASSERT_IS(0, close(childToParent [WRITE_FD]));

      while (true)
      {
        switch (readResult = read(childToParent[READ_FD],
                                  buffer, BUFFER_SIZE))
        {
          case 0: /* End-of-File, or non-blocking read. */
            cout << "End of file reached..."         << endl
                 << "Data received was ("
                 << dataReadFromChild.size() << "): " << endl
                 << dataReadFromChild                << endl;

            ASSERT_IS(pid, waitpid(pid, & status, 0));

            cout << endl
                 << "Child exit staus is:  " << WEXITSTATUS(status) << endl
                 << endl;

            exit(0);


          case -1:
            if ((errno == EINTR) || (errno == EAGAIN))
            {
              errno = 0;
              break;
            }
            else
            {
              FAIL("read() failed");
              exit(-1);
            }

          default:
            dataReadFromChild . append(buffer, readResult);
            break;
        }
      } /* while (true) */
  } /* switch (pid = fork())*/
}

আপনি নির্বাচিত () এবং অ-ব্লকিং রিডের সাথেও প্রায় খেলতে চাইতে পারেন।

fd_set          readfds;
struct timeval  timeout;

timeout.tv_sec  = 0;    /* Seconds */
timeout.tv_usec = 1000; /* Microseconds */

FD_ZERO(&readfds);
FD_SET(childToParent[READ_FD], &readfds);

switch (select (1 + childToParent[READ_FD], &readfds, (fd_set*)NULL, (fd_set*)NULL, & timeout))
{
  case 0: /* Timeout expired */
    break;

  case -1:
    if ((errno == EINTR) || (errno == EAGAIN))
    {
      errno = 0;
      break;
    }
    else
    {
      FAIL("Select() Failed");
      exit(-1);
    }

  case 1:  /* We have input */
    readResult = read(childToParent[READ_FD], buffer, BUFFER_SIZE);
    // However you want to handle it...
    break;

  default:
    FAIL("How did we see input on more than one file descriptor?");
    exit(-1);
}

1
শক্ত উপায়টি সঠিক: আমি সিলেক্ট () কল দিয়ে ধারণাটি পছন্দ করি, যদিও এই ক্ষেত্রে, টাস্কটি শেষ না হওয়া পর্যন্ত আমার আসলে অপেক্ষা করতে হবে। আমার অন্য একটি প্রকল্পের জন্য আমি এই কোডটি রাখব :)
মিশা এম

4
... বা আপনি বিদ্যমান পিক্সিক্স_স্পেনপ ফাংশনটি ব্যবহার করতে পারেন
পার জোহানসন

4
আপনার execlpকলটিতে একটি ত্রুটি রয়েছে: শেষ argপয়েন্টারটি অবশ্যই (char *) NULLভেরিয়ডিক যুক্তি তালিকাটি যথাযথভাবে শেষ করতে হবে ( execlp(3)রেফারেন্সের জন্য দেখুন )।
ক্রিস্টাফ মার্জি

এটি কি ইউনিক্স, লিনাক্স এবং উইন্ডোতে কাজ করবে? আপনি কি দয়া করে হেডার ফাইলগুলি দয়া করে পারেন?
কিট্টু

আপনি কোডটি .bat ফাইলটি কোথায় পাস করছেন?
কিট্টু

33

উইন্ডোজের popenজন্যও এটি কাজ করে তবে এটি কনসোল উইন্ডোটি খোলে - যা আপনার ইউআই অ্যাপ্লিকেশনটির উপরে দ্রুত ঝলক দেয়। আপনি যদি পেশাদার হতে চান তবে এই "ফ্ল্যাশিং" অক্ষম করা ভাল (বিশেষত যদি শেষ ব্যবহারকারী এটি বাতিল করতে পারেন)।

উইন্ডোজের জন্য আমার নিজস্ব সংস্করণটি এখানে রয়েছে:

(কোড কোড এবং এমএসডিএন নমুনায় লিখিত ধারণাগুলি থেকে এই কোডটি আংশিকভাবে পুনরায় সংযুক্ত করা হয়েছে ))

#include <windows.h>
#include <atlstr.h>
//
// Execute a command and get the results. (Only standard output)
//
CStringA ExecCmd(
    const wchar_t* cmd              // [in] command to execute
)
{
    CStringA strResult;
    HANDLE hPipeRead, hPipeWrite;

    SECURITY_ATTRIBUTES saAttr = {sizeof(SECURITY_ATTRIBUTES)};
    saAttr.bInheritHandle = TRUE; // Pipe handles are inherited by child process.
    saAttr.lpSecurityDescriptor = NULL;

    // Create a pipe to get results from child's stdout.
    if (!CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 0))
        return strResult;

    STARTUPINFOW si = {sizeof(STARTUPINFOW)};
    si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.hStdOutput  = hPipeWrite;
    si.hStdError   = hPipeWrite;
    si.wShowWindow = SW_HIDE; // Prevents cmd window from flashing.
                              // Requires STARTF_USESHOWWINDOW in dwFlags.

    PROCESS_INFORMATION pi = { 0 };

    BOOL fSuccess = CreateProcessW(NULL, (LPWSTR)cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
    if (! fSuccess)
    {
        CloseHandle(hPipeWrite);
        CloseHandle(hPipeRead);
        return strResult;
    }

    bool bProcessEnded = false;
    for (; !bProcessEnded ;)
    {
        // Give some timeslice (50 ms), so we won't waste 100% CPU.
        bProcessEnded = WaitForSingleObject( pi.hProcess, 50) == WAIT_OBJECT_0;

        // Even if process exited - we continue reading, if
        // there is some data available over pipe.
        for (;;)
        {
            char buf[1024];
            DWORD dwRead = 0;
            DWORD dwAvail = 0;

            if (!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
                break;

            if (!dwAvail) // No data available, return
                break;

            if (!::ReadFile(hPipeRead, buf, min(sizeof(buf) - 1, dwAvail), &dwRead, NULL) || !dwRead)
                // Error, the child process might ended
                break;

            buf[dwRead] = 0;
            strResult += buf;
        }
    } //for

    CloseHandle(hPipeWrite);
    CloseHandle(hPipeRead);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return strResult;
} //ExecCmd

1
এটি উইন্ডোজের জন্য আমার প্রিয় সমাধান, আমি আশা করি আপনি আমার পরিবর্তনগুলি ক্ষমা করেছেন। আমি কনস্ট-কাস্টকে আরও স্পষ্ট করার পরামর্শ দেব, যেখানে আমি এর স্পষ্ট ব্যবহার wchar_tএবং CreateProcessWঅপ্রয়োজনীয় বাধা হিসাবে বিবেচনা করি ।
ওল্ফ

আপনি এই কাস্টের সাথে কোনও সমস্যা বা সম্ভাব্য সমস্যা দেখছেন? আমি নূন্যতম কোড রাখতে পছন্দ করি এবং প্রয়োজন ছাড়া এটি লিখি না।
টারমোপিকারো

4
ক্রিয়েটপ্রসেস ফাংশন (উইন্ডোজ) পড়ার পরে , আমি এটি করার ক্ষেত্রে একটি প্রকৃত বিপদ দেখতে পাচ্ছি: The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.সুতরাং কলরটির আসল ইনপুটটি পরিবর্তন হতে না দেওয়া, কমান্ড লাইনটিকে প্রথমে একটি আলাদা বাফারে অনুলিপি করা ভাল।
ওল্ফ

এই উত্তরটি স্ট্যাডারকে সঠিকভাবে পরিচালনা করে না।
রেফেল শিঙ্কার

এটি কি ইউনিক্স সিস্টেমগুলির জন্যও কাজ করে? বা ইউনিক্স ডিভাইসের জন্য আমাকে অন্য কিছু ব্যবহার করতে হবে?
255.tar.xz

17

দুটি সম্ভাব্য পন্থা:

  1. আমি মনে করি না যে popen()এটি সি ++ স্ট্যান্ডার্ডের অংশ (এটি মেমোরি থেকে পসিক্সের অংশ), তবে এটি যে ইউনিক্সের সাথে আমি কাজ করেছি তার উপর এটি উপলব্ধ (এবং আপনার কমান্ড হওয়ায় আপনি ইউনিক্সকে লক্ষ্যবস্তু করেছেন বলে মনে হয় ./some_command)।

  2. অফ-সুযোগ যে নেই popen(), আপনি ব্যবহার করতে পারেন system("./some_command >/tmp/some_command.out");, তারপরে আউটপুট ফাইলটি প্রক্রিয়াকরণের জন্য সাধারণ I / O ফাংশন ব্যবহার করুন।


পপেনের জন্য ধন্যবাদ, আমি আপাতত এটি ব্যবহার করতে যাচ্ছি এবং যদি এটি আসে তবে আমি নন-পসিক্স সিস্টেমগুলি নিয়ে উদ্বেগ করব।
মিশা এম

8

কোড :: ব্লকস / মিনজিডাব্লু কেন পপেন / পিস্লোজ অনুপস্থিত তা আমি বুঝতে পারি না । সুতরাং আমি এর পরিবর্তে ক্রেডিটপ্রসেস () এবং ক্রিয়েপ পাইপ () ব্যবহার করে সমস্যার আশপাশে কাজ করেছি।

আমার জন্য কাজ করে এমন সমাধানটি এখানে:

//C++11
#include <cstdio>
#include <iostream>
#include <windows.h>
#include <cstdint>
#include <deque>
#include <string>
#include <thread>

using namespace std;

int SystemCapture(
    string         CmdLine,    //Command Line
    string         CmdRunDir,  //set to '.' for current directory
    string&        ListStdOut, //Return List of StdOut
    string&        ListStdErr, //Return List of StdErr
    uint32_t&      RetCode)    //Return Exit Code
{
    int                  Success;
    SECURITY_ATTRIBUTES  security_attributes;
    HANDLE               stdout_rd = INVALID_HANDLE_VALUE;
    HANDLE               stdout_wr = INVALID_HANDLE_VALUE;
    HANDLE               stderr_rd = INVALID_HANDLE_VALUE;
    HANDLE               stderr_wr = INVALID_HANDLE_VALUE;
    PROCESS_INFORMATION  process_info;
    STARTUPINFO          startup_info;
    thread               stdout_thread;
    thread               stderr_thread;

    security_attributes.nLength              = sizeof(SECURITY_ATTRIBUTES);
    security_attributes.bInheritHandle       = TRUE;
    security_attributes.lpSecurityDescriptor = nullptr;

    if (!CreatePipe(&stdout_rd, &stdout_wr, &security_attributes, 0) ||
            !SetHandleInformation(stdout_rd, HANDLE_FLAG_INHERIT, 0)) {
        return -1;
    }

    if (!CreatePipe(&stderr_rd, &stderr_wr, &security_attributes, 0) ||
            !SetHandleInformation(stderr_rd, HANDLE_FLAG_INHERIT, 0)) {
        if (stdout_rd != INVALID_HANDLE_VALUE) CloseHandle(stdout_rd);
        if (stdout_wr != INVALID_HANDLE_VALUE) CloseHandle(stdout_wr);
        return -2;
    }

    ZeroMemory(&process_info, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&startup_info, sizeof(STARTUPINFO));

    startup_info.cb         = sizeof(STARTUPINFO);
    startup_info.hStdInput  = 0;
    startup_info.hStdOutput = stdout_wr;
    startup_info.hStdError  = stderr_wr;

    if(stdout_rd || stderr_rd)
        startup_info.dwFlags |= STARTF_USESTDHANDLES;

    // Make a copy because CreateProcess needs to modify string buffer
    char      CmdLineStr[MAX_PATH];
    strncpy(CmdLineStr, CmdLine.c_str(), MAX_PATH);
    CmdLineStr[MAX_PATH-1] = 0;

    Success = CreateProcess(
        nullptr,
        CmdLineStr,
        nullptr,
        nullptr,
        TRUE,
        0,
        nullptr,
        CmdRunDir.c_str(),
        &startup_info,
        &process_info
    );
    CloseHandle(stdout_wr);
    CloseHandle(stderr_wr);

    if(!Success) {
        CloseHandle(process_info.hProcess);
        CloseHandle(process_info.hThread);
        CloseHandle(stdout_rd);
        CloseHandle(stderr_rd);
        return -4;
    }
    else {
        CloseHandle(process_info.hThread);
    }

    if(stdout_rd) {
        stdout_thread=thread([&]() {
            DWORD  n;
            const size_t bufsize = 1000;
            char         buffer [bufsize];
            for(;;) {
                n = 0;
                int Success = ReadFile(
                    stdout_rd,
                    buffer,
                    (DWORD)bufsize,
                    &n,
                    nullptr
                );
                printf("STDERR: Success:%d n:%d\n", Success, (int)n);
                if(!Success || n == 0)
                    break;
                string s(buffer, n);
                printf("STDOUT:(%s)\n", s.c_str());
                ListStdOut += s;
            }
            printf("STDOUT:BREAK!\n");
        });
    }

    if(stderr_rd) {
        stderr_thread=thread([&]() {
            DWORD        n;
            const size_t bufsize = 1000;
            char         buffer [bufsize];
            for(;;) {
                n = 0;
                int Success = ReadFile(
                    stderr_rd,
                    buffer,
                    (DWORD)bufsize,
                    &n,
                    nullptr
                );
                printf("STDERR: Success:%d n:%d\n", Success, (int)n);
                if(!Success || n == 0)
                    break;
                string s(buffer, n);
                printf("STDERR:(%s)\n", s.c_str());
                ListStdOut += s;
            }
            printf("STDERR:BREAK!\n");
        });
    }

    WaitForSingleObject(process_info.hProcess,    INFINITE);
    if(!GetExitCodeProcess(process_info.hProcess, (DWORD*) &RetCode))
        RetCode = -1;

    CloseHandle(process_info.hProcess);

    if(stdout_thread.joinable())
        stdout_thread.join();

    if(stderr_thread.joinable())
        stderr_thread.join();

    CloseHandle(stdout_rd);
    CloseHandle(stderr_rd);

    return 0;
}

int main()
{
    int            rc;
    uint32_t       RetCode;
    string         ListStdOut;
    string         ListStdErr;

    cout << "STARTING.\n";

    rc = SystemCapture(
        "C:\\Windows\\System32\\ipconfig.exe",    //Command Line
        ".",                                     //CmdRunDir
        ListStdOut,                              //Return List of StdOut
        ListStdErr,                              //Return List of StdErr
        RetCode                                  //Return Exit Code
    );
    if (rc < 0) {
        cout << "ERROR: SystemCapture\n";
    }

    cout << "STDOUT:\n";
    cout << ListStdOut;

    cout << "STDERR:\n";
    cout << ListStdErr;

    cout << "Finished.\n";

    cout << "Press Enter to Continue";
    cin.ignore();

    return 0;
}

5
ধন্যবাদ! এটি ইন্টারনেটে উইন্ডোজের জন্য সেরা পপেন বাস্তবায়ন! এবং CREATE_NO_WINDOW পতাকাটি পাস করার পরে অবশেষে বিরক্তিকর সিএমডি প্রম্পটগুলি থেকে মুক্তি পাওয়া যেতে পারে that
লাচো তোমভ

1
আপনি কোথায় CREATE_NO_WINDOWজিনিস পাস ?
রেফেল শিঙ্কার

2
@ বিল মুর, যদি আপনি লক্ষ্য করেন তবে আপনার উত্তরটিতে একটি বাগ আছে। ListStdErrকখনও ব্যবহৃত হয় না।
রেফেল শিঙ্কার

7

নিম্নলিখিতটি পোর্টেবল সমাধান হতে পারে। এটি মান অনুসরণ করে।

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <sstream>

std::string ssystem (const char *command) {
    char tmpname [L_tmpnam];
    std::tmpnam ( tmpname );
    std::string scommand = command;
    std::string cmd = scommand + " >> " + tmpname;
    std::system(cmd.c_str());
    std::ifstream file(tmpname, std::ios::in | std::ios::binary );
    std::string result;
    if (file) {
        while (!file.eof()) result.push_back(file.get())
            ;
        file.close();
    }
    remove(tmpname);
    return result;
}

// For Cygwin

int main(int argc, char *argv[])
{
    std::string bash = "FILETWO=/cygdrive/c/*\nfor f in $FILETWO\ndo\necho \"$f\"\ndone ";
    std::string in;
    std::string s = ssystem(bash.c_str());
    std::istringstream iss(s);
    std::string line;
    while (std::getline(iss, line))
    {
        std::cout << "LINE-> " + line + "  length: " << line.length() << std::endl;
    }
    std::cin >> in;
    return 0;
}

4
আমি এই সতর্কতাটি tmpnammkstemp
সিসিসি সহ পেয়েছি

4

স্টোডাউট ক্যাপচার করার জন্য পোসিক্স, সাধারণ কোড ধরে নিচ্ছি:

#include <sys/wait.h>
#include <unistd.h>
#include <string>
#include <vector>

std::string qx(const std::vector<std::string>& args) {
  int stdout_fds[2];
  pipe(stdout_fds);

  int stderr_fds[2];
  pipe(stderr_fds);

  const pid_t pid = fork();
  if (!pid) {
    close(stdout_fds[0]);
    dup2(stdout_fds[1], 1);
    close(stdout_fds[1]);

    close(stderr_fds[0]);
    dup2(stderr_fds[1], 2);
    close(stderr_fds[1]);

    std::vector<char*> vc(args.size() + 1, 0);
    for (size_t i = 0; i < args.size(); ++i) {
      vc[i] = const_cast<char*>(args[i].c_str());
    }

    execvp(vc[0], &vc[0]);
    exit(0);
  }

  close(stdout_fds[1]);

  std::string out;
  const int buf_size = 4096;
  char buffer[buf_size];
  do {
    const ssize_t r = read(stdout_fds[0], buffer, buf_size);
    if (r > 0) {
      out.append(buffer, r);
    }
  } while (errno == EAGAIN || errno == EINTR);

  close(stdout_fds[0]);

  close(stderr_fds[1]);
  close(stderr_fds[0]);

  int r, status;
  do {
    r = waitpid(pid, &status, 0);
  } while (r == -1 && errno == EINTR);

  return out;
}

কোড অবদান আরও কার্যকারিতা জন্য স্বাগত:

https://github.com/ericcurtin/execxx


2

আপনি পাইপ ব্যবহার করে স্ক্রিপ্ট চালানোর পরে আউটপুট পেতে পারেন। আমরা যখন শিশু প্রক্রিয়াটির আউটপুট চাই তখন পাইপ ব্যবহার করি।

int my_func() {
    char ch;
    FILE *fpipe;
    FILE *copy_fp;
    FILE *tmp;
    char *command = (char *)"/usr/bin/my_script my_arg";
    copy_fp = fopen("/tmp/output_file_path", "w");
    fpipe = (FILE *)popen(command, "r");
    if (fpipe) {
        while ((ch = fgetc(fpipe)) != EOF) {
            fputc(ch, copy_fp);
        }
    }
    else {
        if (copy_fp) {
            fprintf(copy_fp, "Sorry there was an error opening the file");
        }
    }
    pclose(fpipe);
    fclose(copy_fp);
    return 0;
}

সুতরাং এখানে স্ক্রিপ্ট, যা আপনি চালাতে চান। আপনার স্ক্রিপ্টটি যে আর্গুমেন্ট গ্রহণ করে (আর্গুমেন্ট না থাকলে কিছুই নয়) এর সাথে একটি কমান্ড ভেরিয়েবল এ রাখুন। আপনি যে ফাইলটি স্ক্রিপ্টের আউটপুট ক্যাপচার করতে চান সেখানে copy_fp এ রাখুন।

সুতরাং পপেন আপনার স্ক্রিপ্টটি চালায় এবং আউটপুটটিকে ফাইপাইপে রাখে এবং তারপরে আপনি কেবল তার আউটপুট ফাইলে সমস্ত কিছু অনুলিপি করতে পারবেন।

এই পদ্ধতিতে আপনি শিশু প্রক্রিয়াগুলির আউটপুট ক্যাপচার করতে পারেন।

এবং অন্য প্রক্রিয়াটি হ'ল আপনি >কেবলমাত্র কমান্ডটিতে অপারেটরকে রাখতে পারেন । সুতরাং আমরা কমান্ডটি চালানোর সময় যদি সমস্ত কিছু একটি ফাইলে রাখি তবে আপনাকে কিছুই অনুলিপি করতে হবে না।

সেক্ষেত্রে পাইপ ব্যবহার করার দরকার নেই। আপনি কেবল ব্যবহার করতে পারেন system, এবং এটি কমান্ডটি চালাবে এবং আউটপুটটিকে সেই ফাইলে রাখবে।

int my_func(){
    char *command = (char *)"/usr/bin/my_script my_arg > /tmp/my_putput_file";
    system(command);
    printf("everything saved in my_output_file");
    return 0;
}

আপনি YoLinux টিউটোরিয়াল পড়তে পারেন : আরও তথ্যের জন্য কাঁটাচামচ, এক্সিকিউট এবং প্রক্রিয়া নিয়ন্ত্রণ


1

নোট করুন যে আপনি ফাইলে আউটপুট পুনর্নির্দেশ করে এবং তারপরে এটি আউটপুট পেতে পারেন

এটি নথিভুক্ত দেখানো হয়েছিল std::system

আপনি WEXITSTATUSম্যাক্রো কল করে প্রস্থান কোড গ্রহণ করতে পারেন ।

    int status = std::system("ls -l >test.txt"); // execute the UNIX command "ls -l >test.txt"
    std::cout << std::ifstream("test.txt").rdbuf();
    std::cout << "Exit code: " << WEXITSTATUS(status) << std::endl;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.