3

出力を生成する別のプロセスからの出力を読み取っています(低速で無限)。このデータをリアルタイムで読み取りたいので、「stdbuf -oL」(行バッファー、データはテキスト)を使用します。生成プロセスを制御できないため、ソースを変更して強制的にフラッシュすることはできません。

これまでのところ、stdbufは問題なく動作しますが、プロセスはSOCK_RAWを使用し、rootとして実行するか、setuid(0)またはcap_net_raw機能を備えている必要があります。setuidまたは機能を使用して非rootとして実行している場合、stdbufは無視されるようです。問題を説明しましょう:

これは単純なライターです。

#include <stdio.h>
#include <unistd.h>

int main(){
        int i;
        for ( i = 0;; i++){
                fprintf(stdout, "%d\n", i);
                sleep(1);
        }
}

そして簡単な読者:

#include <stdio.h>

int main(){
        char* line = NULL;
        size_t n = 0;
        while (getline(&line, &n, stdin) != -1 ) {
                fputs(line, stdout);
        }
}

予想通り、実行./writer | ./readerしてもバッファがいっぱいになるまで何も表示されません。プリペンディングstdbuf -oLはラインバッファリングを有効にし、リーダーにラインを取得します。

% stdbuf -oL ./writer | ./reader
0
1
2
...

しかし、追加すると機能cap_net_raw+epしなくなります。

% sudo setcap cap_net_raw+ep ./writer
% stdbuf -oL ./writer | ./reader
(no output)

setuidを使用した場合も、同じ動作が見られます。

% sudo chown root:root ./writer
% sudo chmod +s ./writer
% stdbuf -oL ./writer | ./reader
(no output)

これが発生する理由と、rootとして実行せずにstdbufを引き続き使用する方法を理解することに興味があります。setuidが舞台裏で何をしているのか完全には理解していないことを認めます。

4

2 に答える 2

3

stdbufソースコードを見ると、LD_PRELOADを設定することで機能しているように見えます。もちろん、setuid実行可能ファイルまたはsudoでLD_PRELOADを使用する場合のセキュリティ上の懸念があります。

私が見つけた1つの提案は、実行可能ファイルのnoatsecureselinux属性を無効にすることでした。

もう1つの簡単なオプションは、stdbufを避けfflush(stdout)、ソースコードから直接呼び出すことです。

于 2012-11-30T16:28:12.753 に答える
2

なしのソリューションLD_PRELOAD

()パッケージunbufferの一部であるユーティリティを使用できます。非常に短いexpectスクリプトです。別のトリックを使用しているので必要ありません。疑似端末(またはなど)を作成するため、を使用して実行されたプロセスは、対話型デバイスに書き込んでいると誤解されます。したがって、デフォルトでは、でラインバッファリングを使用します。expectexpect-develunbufferLD_PRELOADexpectxtermsshunbufferstdout

あなたの場合の使用法:

unbuffer ./writer | ./reader

stdbufプログラムで動作する場合unbufferは、高い確率でも動作します。LD_PRELOADポーズにはいくつかの制限があるためunbuffer、よりも利点がありstdbufます。それとは反対にstdbuf、これらの種類の実行可能ファイルで動作します。

  • setuid
  • ファイル機能付き
  • 静的にリンク
  • 標準を使用しないlibc
于 2013-09-04T21:33:58.403 に答える