標準出力と標準エラー出力をプログラムで読む

 プログラム内で外部コマンドを動かし、その結果を受け取ろうと思いました。このような時は、popen() を使って、外部コマンドの標準出力を読むことが出来ます。

 ところが、今回動かそうとしたコマンドは結果を標準エラー出力に出していて、popen() では読むことが出来ませんでした。

 自前で処理する必要があります。パイプを作成して、fork() します。

    pid_t pid;                // fork() が返す pid
    int pipes[2];             // パイプ
    char *buf[1024];
    File *fp;

    if( pipe(pipes) == -1 ) return 0; // パイプ作成失敗

    pid = fork();
    if( pid == -1 ) return 0; // fork 失敗

    if( pid == 0 ) {          // 子プロセス
        close(pipes[0]);      // 子プロセスは読む必要がないのでパイプを閉じる
        close(1);             // 子プロセスの標準出力を閉じて、
        dup(pipes[1]);        // パイプを標準出力に複製する。
        close(2);             // 子プロセスの標準エラー出力も閉じて、
        dup(pipes[1]);        // パイプを標準エラー出力に複製する。
        close(pipes[1]);      // パイプを閉じておく。

        // コマンドの実行(execl 等)
    }
    close(pipes[1]);          // 親プロセスでは出力しないので閉じる
    if( (fp = fdopen(pipes[0], "r")) != NULL ) { // 読み込みパイプ
        while( fgets(buf, 1023, fp) != NULL ) {
            // 読み込み処理
        }
        fclose(fp);
    }

 dup() 関数は、ファイルディスクリプタを複製しますが、空いている一番若いディスクリプタに複製します。つまり、close(1) で標準出力を閉じるので、その直後の dup(pipes[0]) は標準出力に複製されます。標準エラー出力も同様です。標準出力も標準エラー出力もまとめて読むことが出来ます。

 これで、標準エラー出力に結果を出力するコマンドの結果をプログラム内で読むことが出来ました。

プログラミング

Posted by sirius