Come eseguo un comando e ottengo l'output del comando in C ++ usando POSIX?


463

Sto cercando un modo per ottenere l'output di un comando quando viene eseguito da un programma C ++. Ho esaminato l'utilizzo della system()funzione, ma eseguirà solo un comando. Ecco un esempio di ciò che sto cercando:

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

Ho bisogno di eseguire un comando arbitrario e ottenere il suo output. Ho visto boost.org , ma non ho trovato nulla che mi dia ciò di cui ho bisogno.


Vedi anche le risposte a questa domanda: /programming/52164723/how-to-execute-a-command-and-get-return-code-stdout-and-stderr-of-command-in-cper un'estensione della grande risposta di seguito che fornisce metodi per ottenere il return codee stderrcosì come stdoutquesta risposta già spiega
code_fodder

2
@code_fodder è possibile creare un collegamento a stackoverflow.com/questions/52164723/…
Jonas Stein,

Risposte:


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

Versione pre-C ++ 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;
}

Sostituisci popene pclosecon _popene _pcloseper Windows.


70
Essere consapevoli del fatto che questo afferrerà solo stdout e non stderr .
kalaxy,

14
Inoltre, tenere presente che può verificarsi un'eccezione result += buffer, pertanto la pipe potrebbe non essere chiusa correttamente.
Fred Foo,

6
@Yasky: quando il programma in esecuzione è int main(){ puts("ERROR"); }.
dreamlax,

8
La risposta è buona ma sarebbe meglio se sostituissi 'char * cmd' con 'const char * cmd'
fnc12

29
unique_ptr si adatta meglio qui, dove il conteggio dei riferimenti effettivi non viene mai utilizzato.
Czipperz,

77

Ottenere sia stdout che stderr (e anche scrivere su stdin, non mostrato qui) è facile con la mia intestazione pstreams , che definisce le classi iostream che funzionano come 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
Non sono d'accordo. popenrichiede di utilizzare l'API C stdio, preferisco l'API iostreams. popenrichiede di ripulire manualmente la FILEmaniglia, pstreams lo fa automaticamente. popenaccetta solo a const char*per l'argomento, che richiede attenzione per evitare attacchi di shell injection, pstreams consente di passare un vettore di stringhe simili a execv, che è più sicuro. popennon ti dà nient'altro che una pipa, pstreams ti dice il PID del bambino che ti consente di inviare segnali, ad esempio per ucciderlo se è bloccato o non esce. Tutti questi sono vantaggi anche se si desidera solo un IO unidirezionale.
Jonathan Wakely,

1
Un altro problema con questa soluzione è se il bambino scrive su stderr abbastanza da riempire i buffer e bloccarlo prima che inizi a scrivere su stdout. Il genitore bloccherà la lettura di stdout, mentre il bambino è bloccato in attesa della lettura di stderr. deadlock delle risorse! Almeno uno di questi anelli sarebbe meglio asincrono (cioè filettato).
Jesse Chisholm,

1
@JesseChisholm, sì, potrebbe essere un problema. Ma non è necessario utilizzare i thread perché pstreams consente un'approssimazione di I / O non bloccanti utilizzando l'interfaccia iostream, in particolare utilizzando la funzione readsome , che controlla la disponibilità utilizzando pstreambuf::in_avail(), quindi non si bloccherà. Ciò consente il demultiplexing sullo stdout e sullo stderr del processo, poiché ciascuno ha i dati disponibili. pstreambuf::in_avail()funziona in modo affidabile al 100% solo se il sistema operativo supporta lo ioctl non standard FIONREAD, ma è supportato su (almeno) GNU / Linux e Solaris.
Jonathan Wakely,

13
@chiliNUT la nuova versione 1.0.1 utilizza la licenza Boost.
Jonathan Wakely,

1
@JonathanWakely come posso uccidere l'ipstream dopo un timeout di 5 secondi?
AK,

34

Userei popen () (++ Waqas) .

Ma a volte hai bisogno di leggere e scrivere ...

Sembra che nessuno faccia più le cose nel modo più duro.

(Supponendo un ambiente Unix / Linux / Mac, o forse Windows con un livello di compatibilità POSIX ...)

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())*/
}

Potresti anche voler giocare con select () e letture non bloccanti.

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
Nel modo difficile è giusto :) Mi piace l'idea con la chiamata select (), anche se in questo caso, devo effettivamente aspettare fino al completamento dell'attività. Terrò questo codice per un altro progetto che ho :)
Misha M

4
... oppure potresti usare la funzione posix_spawnp esistente
Per Johansson il

5
La tua execlpchiamata ha un bug: l'ultimo argpuntatore passato deve essere (char *) NULLquello di terminare correttamente la lista degli argomenti variadici (vedi execlp(3)riferimento).
Kristóf Marussy,

Funzionerà su unix, Linux e Windows? Potete per favore anche i file di intestazione?
Kittu,

Dove stai passando il file .bat nel codice?
Kittu,

33

Anche per Windows popenfunziona, ma apre una finestra della console, che lampeggia rapidamente sull'interfaccia utente. Se vuoi essere un professionista, è meglio disabilitare questo "lampeggio" (specialmente se l'utente finale può annullarlo).

Quindi ecco la mia versione per Windows:

(Questo codice è parzialmente ricombinato da idee scritte negli esempi di The Code Project e MSDN.)

#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
Questa è la mia soluzione preferita per Windows, spero che perdonerai le mie modifiche. Suggerirei di rendere il cast più esplicito, mentre considero l'uso esplicito di wchar_te CreateProcessWcome una restrizione non necessaria.
Lupo,

Vedi qualche problema o potenziale problema con questo cast? Preferisco mantenere il codice al minimo e non scriverlo senza necessità.
TarmoPikaro,

4
Dopo aver letto la funzione CreateProcess (Windows) , vedo un vero pericolo nel fare questo: 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.Quindi forse è meglio copiare prima la riga di comando in un buffer separato, per evitare che al chiamante venga modificato l'input originale.
Lupo,

Questa risposta non gestisce correttamente stderr.
Refael Sheinker,

Funziona anche con i sistemi Unix? O dovrei usare qualcos'altro per un dispositivo Unix?
255.tar.xz,

17

Due possibili approcci:

  1. Non credo faccia popen()parte dello standard C ++ (fa parte di POSIX dalla memoria), ma è disponibile su tutti gli UNIX con cui ho lavorato (e sembra che tu stia prendendo di mira UNIX dal momento che il tuo comando lo è ./some_command).

  2. Nel caso in cui non ci sia popen(), è possibile utilizzare system("./some_command >/tmp/some_command.out");, quindi utilizzare le normali funzioni I / O per elaborare il file di output.


Grazie per popen, lo userò per ora e mi preoccuperò dei sistemi non POSIX se questo dovesse succedere.
Misha M,

8

Di seguito potrebbe essere una soluzione portatile. Segue gli standard.

#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
Ricevo questo avviso con gcc: "avviso: l'uso di tmpnamè pericoloso, uso migliore mkstemp"
Mark Lakata,

8

Non riuscivo a capire perché mancasse popen / pclose da Code :: Blocks / MinGW. Quindi ho risolto il problema usando invece CreateProcess () e CreatePipe ().

Ecco la soluzione che ha funzionato per me:

//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
Grazie! Questa è la migliore implementazione popen per Windows su Internet! E passando la bandiera CREATE_NO_WINDOW si può finalmente sbarazzarsi delle fastidiose istruzioni cmd che appaiono.
Lacho Tomov,

1
Dove passi il CREATE_NO_WINDOWcoso?
Refael Sheinker,

2
@Bill Moore, se noti, c'è un bug nella tua risposta. ListStdErrnon viene mai usato.
Refael Sheinker,

4

Supponendo POSIX, semplice codice per catturare stdout:

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

I contributi in codice sono benvenuti per ulteriori funzionalità:

https://github.com/ericcurtin/execxx


2

È possibile ottenere l'output dopo aver eseguito uno script utilizzando una pipe. Usiamo le pipe quando vogliamo l'output del processo figlio.

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

Quindi ecco lo script, che vuoi eseguire. Inseriscilo in una variabile di comando con gli argomenti trattati dallo script (niente se non argomenti). E il file in cui vuoi catturare l'output dello script, mettilo in copy_fp.

Quindi il popen esegue il tuo script e mette l'output in fpipe e quindi puoi semplicemente copiare tutto da quello al tuo file di output.

In questo modo è possibile acquisire gli output dei processi figlio.

E un altro processo è che puoi inserire direttamente l' >operatore solo nel comando. Quindi se inseriremo tutto in un file mentre eseguiamo il comando, non dovrai copiare nulla.

In tal caso, non è necessario utilizzare le pipe. Puoi usare just system, ed eseguirà il comando e inserirà l'output in quel file.

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

Puoi leggere il Tutorial di YoLinux: Fork, Exec e Process control per maggiori informazioni.


1

Si noti che è possibile ottenere l'output reindirizzando l'output sul file e quindi leggendolo

È stato mostrato nella documentazione di std::system

È possibile ricevere il codice di uscita chiamando la WEXITSTATUSmacro.

    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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.