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


20

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

使用例は次のとおりstdoutです。バックグラウンドで長時間実行して、大量の出力をに出力するプロセスがあるとします。私は出力をあまり気にせず、それを保存したくはありません(おそらく十分なスペースがありません)そしてその仕事をするためにそれを残します。そのため、この理論上のバッファリングされた非ブロッキングの名前付きパイプに出力をリダイレクトし、定期的にそれを利用したいと思います。

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

mkmagicfifo magicfifo 10M
spewingprocess > magicfifo &

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

tail -f magicfifo

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

私はすべてのデータをどこかに保存する必要があるので、それを含むソリューションはそれを含むtailまたはそれpruneを行うとは思いません(まあ、私はそれを含む回避策を考えることができます)そして、すべての出力を生成するプロセスのリダイレクトを壊す(私はこれを証明して/試していない認めるよ)おそらく、ファイルを書き換える必要があります。tailtailprune

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

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


1
説明しているのは、「リングバッファ」または「循環バッファ」です。作成するのは簡単ですが、そのようなことを維持するためのコマンドラインツールは知りません。
ショーンJ.ゴフ

2
「Linuxノンブロッキングfifo(オンデマンドロギング)」、stackoverflow.com/questions/7360473/…で説明されているソリューションをご覧ください

1
このように見えますがStackOverflowの上で解決されています stackoverflow.com/questions/7360473/...を
ジェームス・ブラックバーン

@JamesBlackburn:ありがとう!とても興味深い。
TJクラウダー

回答:


16

あなたが探しているのはGNUだと思いますscreen。1つまたは複数のプログラムからの最後の画面または2つの出力を保持するためのバッファーを維持し、切断して後で戻ることができます。


画面を提案するための+1。ところで、多くの「履歴行」を保持するように構成できます。
シュンツ氏

1
ありがとう。私の質問で示したコマンドにそれをどのように適用するかの例を教えてください。マニュアルページには、それがウィンドウマネージャーであると書かれています(それらはグラフィカルな意味ではなく、最終的な意味であると思いますが、それでもなおそうです)。そして、私はまだ(ssh経由で)ドロップインして必要に応じてドロップアウトできますか?(たとえば、リモートサーバーでの操作。)
TJクラウダー

はい、GNU screenをこの方法で使用できます。新しい(潜在的に名前が付けられた)セッションを作成し、そのセッション内でコマンドを実行してから切断します。
TML

2
そこもだtmuxdtach-ターミナルマルチプレクサ/セッションマネージャアプリケーションの同じクラスのものは、同じことを達成することができるはずです。
-jw013

5

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

sprewingprocess | pv -B 1g > ordinaryfifo &

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


ありがとう、しかし、ターゲットの名前付きパイプを読み取っていなかった場合、バッファがいっぱいになったらそのブロックはありませんか?
TJクラウダー

1
はい、しかしあなたにはどんな選択肢がありますか?有限の宇宙では、文字通り無制限のバッファリングを行うことはできません。
デビッドシュワルツ

他の選択肢は、私の質問で説明したとおりです:すべての出力を保存しない。バッファーがいっぱいになると、最も古いものが破棄されます。
TJクラウダー

うーん、私はこれをテストしましたが、残念ながら完全に機能しません。fifoを読み取るプロセスがしばらく読み取りを停止すると、pvはfifoへの書き込みをブロックします。マルチスレッドではないため、pvのバッファーへのデータの読み取りもブロックします。そのため、pfoのバッファーは、fifoを読み取るプロセスが読み取りを続けている間のみ、満たされ続けます。pvは一部のデータを読み取ってバッファリングできますが、ライターが完全にブロックするのを防ぐことはできません。
ダニエルS.スターリング14年

1

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

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

次に、tailを使用してファイルから読み取ります(2> /dev/null「ファイルが切り捨てられた」エラーメッセージは削除されます)。

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

この方法では、バッファは成長せず、多重化できます。たとえば、必要なだけテールを実行します。ただし、このアプローチの問題は、このテストが示すように、tailが読み取るよりも速く切り捨てるとデータを失う可能性があることです。

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

それでも、データの損失をあまり気にかけない場合、またはデータの損失が発生するためにspewingprocessが十分に速くない場合、これは良い解決策のようです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.