ti-enxame.com

Como capturar o exit_code e stderr do comando que é executado em C ++?

Estou escrevendo um programa c ++ que executa e gera (em tempo real) um script Shell, makefile ou apenas outro programa. No entanto, eu gostaria que meu programa retornasse de maneira diferente quando houver erros ou nenhum erro.

#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's executed
    while(fgets(buff, sizeof(buff), in)!=NULL){
        cout << buff;
    }
    pclose(in);
    return 0;



}

é o que eu tenho até agora.

Digamos que esse script executou make para criar um programa e deu um erro como esse

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
  • É possível que eu saiba que isso ocorreu com erro?

    • Isso sai com o código else than 0 já que é um erro?

    • Essa última parte é produzida em stderr?

Considerando que make saiu com o código não 0, Digamos 1, e ele sai em stderr, não é possível capturar esses códigos de saída e mensagem de erro no final?

Como capturar o código de saída e stderr após a saída dos resultados do programa e retornar o exit code/stderr na função?

17
Logan

Se você estiver interessado no código de erro, é uma maneira mais portátil de obtê-lo, em vez de dividir por 256:

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

No entanto, popen é uma maneira, então você está criando outras soluções alternativas pelo estilo de redirecionamento usual no Shell ou segue este código não testado para fazer o certo:

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

/* since pipes are unidirectional, we need two pipes.
   one for data to flow from parent's stdout to child's
   stdin and the other for child's stdout to flow to
   parent's 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");
        }
    }
}

O código é daqui:

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

15
lpapp

O valor de retorno do processo filho está no topo 16 8 bits. Você precisa dividir o valor retornado de pclose por 256 e obter o valor de retorno pesquisado do processo filho.

Obtido em http://bytes.com/topic/c/answers/131694-pclose-returning-termination-status-command

Minha resposta seria pclose(in)/256 é o código de saída.

Ainda não sei como capturar stderr ou sdtout de maneira diferente, mas até que haja uma resposta, aceitarei isso como minha resposta.

11
Logan

Obrigado pela resposta sobre o código de saída Logan.

Eu acredito que uma viagem de ida e volta para obter stderr seria redirecioná-lo para um arquivo temporário:

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