2013-04-02 22 views
6

Linuxコマンドの出力文字列とC++プログラムのコマンド出力ステータスを取得します。私は自分のアプリケーションでLinuxコマンドを実行しています。例えばlinuxコマンドの出力文字列と出力ステータスをC++で取得する方法

: コマンド:

は、rmdir ABCD

コマンド出力文字列:

は、rmdir:そのようなファイルまたはディレクトリ

: `ABCD 'を削除できませんでした

コマンドSt ATU:

は私が私のコマンドの出力文字列を与えるLinuxの出力状態を与える関数system()、および機能popen()を使用してみました(コマンドが失敗した意味)1、どちらも機能 の出力文字列とLinuxコマンドの出力ステータスの両方が表示されます。

+1

C++を使用している場合、なぜ質問にCタグが付きますか? –

答えて

7

出力文字列は標準出力または標準エラー記述子(それぞれ1または2)です。

あなたは(たとえば - POSIX pipeを)それらを読むことができる場所に(dupdup2機能を見てみましょう)これらのストリームをリダイレクトする必要があります。

int pd[2]; 
int retValue; 
char buffer[MAXBUF] = {0}; 
pipe(pd); 
dup2(pd[1],1); 
retValue = system("your command"); 
read(pd[0], buffer, MAXBUF); 

今、あなたが持っている(の一部)あなたのバッファに出力し、retValueでリターンコード:

はCで、私はこのような何かをしたいです。

また、exec(つまりexecve)の関数を使用して、戻り値をwaitまたはwaitpidとすることができます。

更新:これは標準出力のみをリダイレクトします。標準エラーをリダイレクトするには、dup2(pd[1],1)を使用します。

+0

これは本当ですか?シェルプロセスが終了するまで、 'system()'は返ってこないと思っていました。また、子の出力が大きい場合、 'stdout'への書き込みがブロックされ、デッドロックが発生する可能性があります。子プロセスが終了したときにデータが既にパイプに入っているため、デッドロックが問題になる可能性があるので、私はうまくいきません。 – FatalError

+0

出力のサイズがパイプのサイズ(私のマシンではデフォルトで65536)より大きい場合、これはブロックされる可能性があります。これが予想される場合は、fork + execが優先されます。しかし、そうでない場合(なぜなら、ケースがわかっており、出力サイズが制限されている場合)、なぜ気になるのでしょうか? :) –

+0

もちろん、十分です。興味深い戦略の+1 +1 – FatalError

2

残念ながら、これを行うにはLinux上のCには簡単で簡単な方法はありません。 Here's子プロセスのstdout/stderr/stdinを正しく読み書きする方法の例。

そして、あなたは終了コードを受信したいときは、(完全な例が提供ページの下部に設けられている)waitpidを使用する必要があります。

endID = waitpid(childID, &status, WNOHANG|WUNTRACED); 

は今、あなたはちょうど一緒にそれらの2に参加する必要があり:)

はに関する詳細な情報を含む(ALP)をrogramming Pinux Lをdvancedという名前の偉大な無料の本もあります利用可能な問題の種類はhereです。

+0

これらの問題についてはhttp://advancedlinuxprogramming.com/に章全体があります –

+0

@BasileStarynkevitchああ、ALP、それを完全に忘れてしまった...私はそれを答えに加える。 – Vyktor

3

最も簡単な解決策は、systemを使用し、標準出力と標準エラーを一時ファイルにリダイレクトすることです。後で削除することができます。

0

popenシステムコールを使用すると、出力をファイルにリダイレクトし、ファイルから出力を文字列にリダイレクトできます。以下のような:詳細については

char buffer[MAXBUF] = {0}; 
    FILE *fd = popen("openssl version -v", "r"); 
    if (NULL == fd) 
    { 
     printf("Error in popen"); 
     return; 
    } 
    fread(buffer, MAXBUF, 1, fd); 
    printf("%s",buffer); 

    pclose(fd); 

popenためmanページをお読みください。

1

上記のPiotr Zierhofferの回答を基にして、ここでは関数を使ってstdoutとstderrを元の状態に戻します。

// Execute command <cmd>, put its output (stdout and stderr) in <output>, 
// and return its status 
int exec_command(string& cmd, string& output) { 
    // Save original stdout and stderr to enable restoring 
    int org_stdout = dup(1); 
    int org_stderr = dup(2); 

    int pd[2]; 
    pipe(pd); 

    // Make the read-end of the pipe non blocking, so if the command being 
    // executed has no output the read() call won't get stuck 
    int flags = fcntl(pd[0], F_GETFL); 
    flags |= O_NONBLOCK; 

    if(fcntl(pd[0], F_SETFL, flags) == -1) { 
     throw string("fcntl() failed"); 
    } 

    // Redirect stdout and stderr to the write-end of the pipe 
    dup2(pd[1], 1); 
    dup2(pd[1], 2); 
    int status = system(cmd.c_str()); 
    int buf_size = 1000; 
    char buf[buf_size]; 

    // Read from read-end of the pipe 
    long num_bytes = read(pd[0], buf, buf_size); 

    if(num_bytes > 0) { 
     output.clear(); 
     output.append(buf, num_bytes); 
    } 

    // Restore stdout and stderr and release the org* descriptors 
    dup2(org_stdout, 1); 
    dup2(org_stderr, 2); 
    close(org_stdout); 
    close(org_stderr); 

    return status; 
} 
関連する問題