web-dev-qa-db-ja.com

非ブロッキングのバッファ付き名前付きパイプ?

私は存在しないと思われるものを探しています:コマンドラインから使用するための非ブロッキングのバッファー付き名前付きパイプ(fifo)。そんなことありますか?

これがユースケースです:バックグラウンドで長時間実行されるプロセスがあり、大量の出力をstdoutに出力するとします。出力は本当に気にせず、保存したくありません(おそらく十分なスペースがないためです)が、定期的に「立ち寄り」、それが行っていることを追跡し、その後再びドロップしたい任せて仕事をします。そのため、出力をこの理論上のバッファリングされた非ブロッキング名前付きパイプにリダイレクトし、定期的にそれを利用したいと思います。

だから基本的に私はこのように始めたいです(10Mはバッファのサイズです):

mkmagicfifo magicfifo 10M
spewingprocess > magicfifo &

...そして定期的に立ち寄って、何が起こっているかを確認します...

tail -f magicfifo

...なしmagicfifoすべての出力を保存する(つまり、通常のファイルではない)、そしてなしいっぱいになったときに、吐き出しプロセスをブロックするタップされません(したがって、通常の名前付きパイプではありません)。

tailがまだ解決しないので、Pruneまたはtailを含むソリューションがそれを実行するとは思いません(まあ、tailを含む回避策は考えられます)。すべてのデータをどこかに格納する必要があります(ドロップインしたりドロップアウトしたい場合)、_Pruneはファイルを書き換える必要があります(おそらく私は試したことも証明したこともないことを認めます)これ)すべての出力を生成するプロセスのリダイレクトを壊す。

私はこれを行うためのユーティリティを書くことができると思いますが、* nixにはファイルとパイプなどのso manyクールな側面があるため、これは存在すると思いますが、知らないそれについて。

だから:そのようなことはありますか?

20
T.J. Crowder

あなたが探しているのはGNU screenです。1つ以上のプログラムからの出力の最後の1つまたは2つをフルに保持するためのバッファを維持し、切断して来ることができます後で戻る。

16
psusi

pv を使用できます。パイプラインで必要なだけのバッファリングを提供します。次のように使用できます。

sprewingprocess | pv -B 1g > ordinaryfifo &

これにより、spewingprocessとfifoの間で最大1GBのバッファリングが可能になります。ほとんどのLinuxディストリビューションでは、pvを、信じられないかもしれませんが、pvというパッケージで提供しています。

5
David Schwartz

私も同じ問題を抱えていました。これが私の最初の解決策です。最初に出力をファイルに書き込みます。ファイルが無制限に大きくならないように、各行の後で切り捨てます。

spewingprocess | while read line; do echo $line > buffer.txt ; done

次に、tailを使用してファイルから読み取ります(ここで2> /dev/null「ファイルが切り捨てられました」というエラーメッセージが表示されなくなります):

tail -f ./buffer.txt 2> /dev/null

このようにして、バッファは増大せず、多重化できます。好きなだけ尾を実行します。ただし、この方法の問題は、このテストが示すように、末尾が読み取れるよりも速く切り捨てるとデータが失われる可能性があることです。

for ((i=0; ; i++)) ; do echo "$i" ; done | while read line; do  echo $line > buffer.txt ; done
tail -f ./buffer.txt 2> /dev/null > log.txt

しばらく実行した後、最初と最後の行は次のとおりです。

$ head -n 1 log.txt
0
$ tail -n 1 log.txt
78783

ただし、ファイルの行数が少ないため、一部が失われます。

$ wc log.txt
67087  67087 392819 log.txt

それでも、データの損失をそれほど気にしない場合、または吐き出しプロセスがデータの損失が発生するほど速くない場合は、これは良い解決策のようです。

1
bterwijn