コマンドラインプログラムが出力がリダイレクトされるのを防ぐことはできますか?

コマンドラインプログラムが出力がリダイレクトされるのを防ぐことはできますか?

私はこれをするのに慣れています。 someprogram >output.file

私はプログラムで生成された出力をファイルに保存したいときはいつでもこれを行います。私もこれの2つのバリエーションを知っていますIOリダイレクト:

  • someprogram 2>output.of.stderr.file (標準誤差の場合)
  • someprogram &>output.stderr.and.stdout.file(stdout + stderrの組み合わせの場合)

今日は不可能だと思った状況に直面しました。次のコマンドを使用すると、期待xinput test 10どおりに次の結果が表示されます。

user@hostname:~$xinput テスト 10
ボタン30
リリースキー30
ボタン40
キーリリース40
ボタン32
キーリリース32
ボタン 65
キーリリース65
ボタン61
キーリリース61
ボタン 31
^C
ユーザー@ホスト名:~$

私はこの出力がいつものようにファイルに保存されることを期待しました。たとえば、.を使用しましたが、xinput test 10 > output.file私の期待とは異なり、出力.ファイルファイルは空でした。これはまた、xinput test 10 &> output.filestdoutやstderrで何かを見逃さないようにするためです。

本当に混乱しています。xinput出力がリダイレクトされるのを防ぐ方法があるかどうか、ここでプログラムに問い合わせてみましょう。

修正する

ソースコードを見ました。このコードによって出力が生成されたようです(下記のコードスニペットを参照)。出力は通常のprintfによって生成されるようです。

//test.c ファイルから

静的無効 print_events(*dpy 表示)
{
    XEventイベント;

    そして(1){
    XNextEvent(dpy、&イベント);

    // [...いくつかの異なるイベントタイプがここにリストされています...]

        if((Event.type == key_press_type) ||
           (Event.type == key_release_type)) {
        整数ループ;
        XDeviceKeyEvent *key = (XDeviceKeyEvent *) &Event;

        printf("key %s %d ", (Event.type == key_release_type) ? "release" : "押された", key->keycode);

        for(loops=0;loopaxes_count;loop++){
        printf("a[%d]=%d ", key->first_axis + loop, key->axis_data[loop]);
        }
        printf("\n");
    }
    }
}

stderrから出力コピーを取得できるように、ソースコードをこれ(以下の次のコードスニペットを参照)に変更しました。この出力をリダイレクトできます。

//test.c ファイルから

静的無効 print_events(*dpy 表示)
{
    XEventイベント;

    そして(1){
    XNextEvent(dpy、&イベント);

    // [...いくつかの異なるイベントタイプがここにリストされています...]

        if((Event.type == key_press_type) ||
           (Event.type == key_release_type)) {
        整数ループ;
        XDeviceKeyEvent *key = (XDeviceKeyEvent *) &Event;

        printf("key %s %d ", (Event.type == key_release_type) ? "release" : "押された", key->keycode);
        fprintf(stderr,"key %s %d ", (Event.type == key_release_type) ? "release" : "press ", key->keycode);

        for(loops=0;loopaxes_count;loop++){
        printf("a[%d]=%d ", key->first_axis + loop, key->axis_data[loop]);
        }
        printf("\n");
    }
    }
}

現在の私の考えは、リダイレクトを実行すると、プログラムがメジャーリリースイベントを監視する機能を失う可能性があることです。

ベストアンサー1

stdout が端末でない場合にのみ出力がバッファリングされます。

を押すと、Ctrl-Cそのバッファがまだ書き込まれていないため失われます。

何でも使用すると同じ動作が得られますstdio。たとえば、次のようになります。

grep . > file

空でない行を入力してキーを押すと、Ctrl-Cファイルが空であることがわかります。

一方、次のように入力します。

xinput test 10 > file

その後、キーボードで十分に入力してください。バッファー全体(最小4k出力)を取得すると表示できます。文書一度に4kずつ増加します。

を使用すると、forと入力してバッファをフラッシュして正常にシャットダウンgrepできます。の場合にはそんなオプションがないと思います。Ctrl-Dgrepxinput

バッファリングはstderrデフォルトでは行われないので、他の動作が発生する理由を説明します。fprintf(stderr)

xinput.c1つを追加すると、つまり受信時に正常に終了するように指示するsignal(SIGINT, exit)と、もはやnullではないことがわかります(信号ハンドラでライブラリ関数を呼び出すことが安全であると保証されないため、競合しないと仮定)。 printfがバッファに書き込むかどうかを検討してください。これは、信号が領域に入ると発生します。xinputSIGINTfile

可能であれば、次のstdbufコマンドを使用してバッファリング動作を変更できますstdio

stdbuf -oL xinput test 10 > file

持つこのサイトに質問がたくさんあります。このオーバーライドは無効になります。標準入出力バッファリングを入力すると、より多くの代替ソリューションを見つけることができます。

おすすめ記事