2013-02-25 3 views
12

나는 쉘 스크립트, 메이크 파일 또는 다른 프로그램을 (실시간으로) 실행하고 출력하는 C++ 프로그램을 작성 중이다. 그러나 오류가 있거나 오류가없는 경우 내 프로그램을 다르게 반환하고 싶습니다.C++에서 실행되는 명령의 exit_code 및 stderr를 캡처하는 방법은 무엇입니까?

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



} 

내가 지금까지 가지고있는 것입니다.

은의이 스크립트 프로그램을 구축 할 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을 반환 할 수 있습니다?

+3

만일 pclose는 종료 상태를 반환합니다. –

+0

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

답변

13

이 그것을 얻기보다는 더 휴대용 방법은 다음과 같습니다

나는 표준 오류를 얻을 수있는 왕복 임시 파일로 리디렉션하는 것입니다 생각 256로 나누어 그러나

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

, 당신도 쉘에서 보통 재 스타일에 의해 더 해결 방법을 만들 수 있도록 popen 하나의 방법은, 또는 당신이 바로 그것을 할이 테스트되지 않은 코드를 따르

,691,363 (210)
#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"); 
     } 
    } 
} 

코드는 여기에서있다 :

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

+1

필자에게''WEXITSTATUS'와''pclose()'를 사용하면 성공하면'1', 실패 할 경우'-1'을 반환합니다. 이 소리가 맞습니까? 아니면 제가 잘못한 것을 했습니까? –

+0

@ AndyJ0076 : 괜찮아 보인다. – lpapp

+0

다른 0이 아닌 종료 코드와 관련하여 https://groups.google.com/forum/#!topic/utah-c/g4MpZVnJ7es에 대한 설명이 있습니다 –

9

하위 프로세스의 반환 값은 상단에 있습니다. 8 비트. 에 pclose의 반환 값을 256으로 나누면 자식 프로세스의 검색된 반환 값은 입니다.

pclose(in)/256이 종료 코드 인 것 http://bytes.com/topic/c/answers/131694-pclose-returning-termination-status-command

내 대답에서 건 졌어요.

나는 여전히 stderr 또는 sdtout을 어떻게 다르게 잡을 지 모르지만 거기에 대한 답이있을 때까지 이것을 내 대답으로 받아 들일 것입니다.

+0

여기에서 같은 문제가 발생합니다. 공개 질문에 대한 해결책을 찾았습니까? 내 해결 방법은 stderr를 파일로 파이핑하고 popen 호출로 다시 읽는 것입니다. – Strubbl

+1

@Strubbl 종류 ... 체크 아웃 https://github.com/aponxi/npm-execxi/blob/master/execxi.cpp 쉘 명령어를 실행하기 위해 nodejs에 C++ 확장을 작성했습니다. 나는 stderr와 stdout을 나누어 구현하지 않았다고 생각한다. stderr을 에러로 사용하는 모든 프로그램이 내가 생각한 것이 아니기 때문이다. 그리고 저는'읽기보다는 파일 쓰기 '를 막기 위해 뭔가를 생각해 냈습니다. 그 코드에서 내가 한 것을 읽는 것이 도움이 되길 바란다. (잠시 동안 세부 사항이 모호 해졌다.) – Logan

+1

쉘 리다이렉션, 2> & 1을 사용하고 오류 메시지를 검색 할 수도있다. – ChuckCottrill

0

종료 코드 Logan에 대한 답장을 보내 주셔서 감사합니다.

오류 코드에 관심이 있다면
FILE* f = popen("cmd 2>/tmp/tmpfile.txt", "r"); 
+1

2 개 이상의 복사본을 실행해야 할 때 유용한 출력을 얻을 수 있도록 고유 한 출력 파일 (아마도 pid를 사용하여)을 만듭니다. – ChuckCottrill

+0

'tempnam','tmpfile' 또는'tmpnam'을 사용하여 임시 파일을 생성하십시오. ** 절대 ** 하드 코드하지 마십시오. – rsp