Как захватить exit_code и stderr команды, запущенной на С++?

Я пишу С++-программу, которая выполняет и выводит (в режиме реального времени) оболочку script, makefile или только другую программу. Однако я хотел бы, чтобы моя программа возвращалась по-разному, когда есть ошибки или ошибки.

#include "execxi.h"



using namespace std;


int execXI::run(string command)
{

    FILE *in;
    char buff[512];
    // is this the check for command execution exited with not 0?
    if(!(in = popen(command.c_str(), "r"))){
            // I want to return the exit code and error message too if any
        return 1;
    }
    // this part echoes the output of the command that executed
    while(fgets(buff, sizeof(buff), in)!=NULL){
        cout << buff;
    }
    pclose(in);
    return 0;



}

- это то, что у меня есть.

Скажем, этот script выполнил make для создания программы и дал такую ​​ошибку

on_target_webkit_version out/Release/obj/gen/webkit_version.h
Traceback (most recent call last):
  File "../build/webkit_version.py", line 107, in <module>
    sys.exit(main())
  File "../build/webkit_version.py", line 103, in main
    return EmitVersionHeader(*sys.argv[1:])
  File "../build/webkit_version.py", line 86, in EmitVersionHeader
    webkit_revision = GetWebKitRevision(webkit_dir, version_file)
  File "../build/webkit_version.py", line 60, in GetWebKitRevision
    version_info = lastchange.FetchVersionInfo(
AttributeError: 'module' object has no attribute 'FetchVersionInfo'
make: *** [out/Release/obj/gen/webkit_version.h] Error 1
  • Возможно ли, чтобы я знал, что это произошло с ошибкой?

    • Выполняется ли это с кодом else than 0, поскольку это ошибка?

    • Это последняя часть, выведенная в stderr?

Учитывая, что make вышел с кодом не 0, скажем, 1, и он выводит в stderr, не возможно ли, чтобы я в конце концов смог записать эти коды выхода и сообщение об ошибке?

Как я могу захватить код выхода и stderr после вывода результатов программы и вернуть exit code/stderr в функцию?

Ответ 1

Если вас интересует код ошибки, это более переносимый способ получить его, а не делить на 256:

printf("Exit code: %i\n", WEXITSTATUS(pclose(fp)));

Однако popen является одним из способов, поэтому вы создаете дополнительные обходные пути с помощью обычного стиля перенаправления в оболочке или следуете этому непроверенному коду, чтобы сделать это правильно:

#include <unistd.h>
#include <stdio.h>

/* since pipes are unidirectional, we need two pipes.
   one for data to flow from parent stdout to child's
   stdin and the other for child stdout to flow to
   parent stdin */

#define NUM_PIPES          2

#define PARENT_WRITE_PIPE  0
#define PARENT_READ_PIPE   1

int pipes[NUM_PIPES][2];

/* always in a pipe[], pipe[0] is for read and 
   pipe[1] is for write */
#define READ_FD  0
#define WRITE_FD 1

#define PARENT_READ_FD  ( pipes[PARENT_READ_PIPE][READ_FD]   )
#define PARENT_WRITE_FD ( pipes[PARENT_WRITE_PIPE][WRITE_FD] )

#define CHILD_READ_FD   ( pipes[PARENT_WRITE_PIPE][READ_FD]  )
#define CHILD_WRITE_FD  ( pipes[PARENT_READ_PIPE][WRITE_FD]  )

void
main()
{
    int outfd[2];
    int infd[2];

    // pipes for parent to write and read
    pipe(pipes[PARENT_READ_PIPE]);
    pipe(pipes[PARENT_WRITE_PIPE]);

    if(!fork()) {
        char *argv[]={ "/usr/bin/bc", "-q", 0};

        dup2(CHILD_READ_FD, STDIN_FILENO);
        dup2(CHILD_WRITE_FD, STDOUT_FILENO);

        /* Close fds not required by child. Also, we don't
           want the exec'ed program to know these existed */
        close(CHILD_READ_FD);
        close(CHILD_WRITE_FD);
        close(PARENT_READ_FD);
        close(PARENT_WRITE_FD);

        execv(argv[0], argv);
    } else {
        char buffer[100];
        int count;

        /* close fds not required by parent */       
        close(CHILD_READ_FD);
        close(CHILD_WRITE_FD);

        // Write to child’s stdin
        write(PARENT_WRITE_FD, "2^32\n", 5);

        // Read from child’s stdout
        count = read(PARENT_READ_FD, buffer, sizeof(buffer)-1);
        if (count >= 0) {
            buffer[count] = 0;
            printf("%s", buffer);
        } else {
            printf("IO Error\n");
        }
    }
}

Код отсюда:

http://jineshkj.wordpress.com/2006/12/22/how-to-capture-stdin-stdout-and-stderr-of-child-program/

Ответ 2

Возвращаемое значение дочернего процесса находится в верхнем 16 8 бит. У тебя есть для деления возвращаемого значения pclose на 256, вы получаете поиск возвращаемого значения дочернего процесса.

Извлечен из http://bytes.com/topic/c/answers/131694-pclose-returning-termination-status-command

Ответом будет pclose(in)/256 код выхода.

Я до сих пор не знаю, как записывать stderr или sdtout по-другому, но пока не будет ответа на этот вопрос, я буду принимать это как свой ответ.

Ответ 3

Спасибо за ответ о выходе кода Logan.

Я считаю, что в оба конца получить stderr было бы перенаправить его во временный файл:

FILE* f = popen("cmd 2>/tmp/tmpfile.txt", "r");