2013-02-25 16 views
12

Tôi đang viết một chương trình C++ thực thi và xuất ra (trong thời gian thực) một kịch bản lệnh shell, makefile hoặc chỉ một chương trình khác. Tuy nhiên, tôi muốn chương trình của tôi trở lại khác nhau khi có lỗi hoặc không có lỗi.Cách chụp exit_code và stderr của lệnh được chạy trong C++?

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



} 

là những gì tôi có cho đến nay.

Hãy nói rằng kịch bản này chạy make để xây dựng một chương trình và nó đã cho một lỗi như vậy

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 
  • Có thể cho tôi biết rằng điều này đã thoát với lỗi?

    • Điều đó có thoát với mã else than 0 vì đó là lỗi không?

    • Phần cuối cùng có xuất hiện trong stderr không?

Xét rằng make thoát với mã không 0, chúng ta hãy nói 1, và nó ra trong stderr là nó không thể cho tôi để nắm bắt các mã lối ra và thông báo lỗi cuối cùng?

Làm cách nào tôi có thể nắm bắt mã thoát và stderr sau khi xuất kết quả của chương trình và trả lại exit code/stderr trong chức năng?

+3

pclose trả về một trạng thái thoát. –

+0

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

Trả lời

13

Nếu bạn quan tâm trong các mã lỗi, đây là một cách di động nhiều hơn nhận nó chứ không phải là chia cho 256:

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

Tuy nhiên, popen là một cách, vì vậy bạn là một trong hai cách giải quyết sáng tạo hơn nữa bởi phong cách chuyển hướng bình thường trong vỏ, hoặc bạn làm theo đang chưa được kiểm tra này để làm điều đó đúng:

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

Mã này là từ đây:

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

+1

Với tôi, sử dụng 'WEXITSTATUS' với' pclose() 'là trả về' 1' cho thành công và '-1' cho không thành công. Điều này có đúng không, hoặc tôi đã làm gì sai? –

+0

@ AndyJ0076: có vẻ ổn với tôi. – lpapp

+0

có giải thích https://groups.google.com/forum/#!topic/utah-c/g4MpZVnJ7es về các mã thoát khác nhau 0 –

9

Giá trị trả lại của quy trình con nằm ở đầu 8 bit. Bạn có để chia giá trị trả về của pclose theo 256, sau đó bạn nhận được giá trị trả về tìm kiếm của quy trình con là .

nhận từ http://bytes.com/topic/c/answers/131694-pclose-returning-termination-status-command

câu trả lời của tôi sẽ là pclose(in)/256 là mã thoát.

Tôi vẫn không biết cách chụp stderr hoặc sdtout khác nhau nhưng cho đến khi có câu trả lời cho rằng tôi sẽ chấp nhận điều này làm câu trả lời của tôi.

+0

Cùng một vấn đề ở đây. Bạn có tìm thấy giải pháp cho câu hỏi mở của mình không? Cách giải quyết của tôi là đường ống vào một tập tin và đọc lại với một cuộc gọi popen. – Strubbl

+1

@Strubbl Loại ... kiểm tra này ra https://github.com/aponxi/npm-execxi/blob/master/execxi.cpp Tôi đã viết một phần mở rộng C++ cho nodejs để thực thi lệnh shell. Tôi nghĩ rằng tôi đã không thực hiện phân chia stderr và stdout vì không phải tất cả các chương trình sử dụng stderr cho các lỗi là những gì tôi figured. Và tôi tin rằng tôi đã nghĩ ra một cái gì đó để ngăn chặn phương pháp tiếp cận 'viết thư hơn đọc'. Tôi hy vọng đọc những gì tôi đã làm trong mã đó giúp (nó đã được một thời gian vì vậy tôi mờ về các chi tiết.) – Logan

+1

Bạn cũng có thể sử dụng chuyển hướng vỏ, 2> & 1, và tìm kiếm các thông báo lỗi. – ChuckCottrill

0

Cảm ơn bạn đã trả lời về mã thoát Logan.

Tôi tin rằng một chuyến đi vòng quanh để có được stderr sẽ được chuyển hướng nó vào một tập tin tạm thời:

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

Tạo tệp đầu ra duy nhất (có thể sử dụng pid), để khi bạn cần chạy hơn 2 bản sao, bạn sẽ nhận được kết quả hữu ích. – ChuckCottrill

+0

Sử dụng 'tempnam',' tmpfile' hoặc 'tmpnam' để tạo tệp thời gian, ** không bao giờ ** mã hóa tên. – rsp

Các vấn đề liên quan