出力が非常に大きいパイプラインコマンド

出力が非常に大きいパイプラインコマンド

tarディレクトリをインポートして結果を作成し、stdout次のようにコンプレッサにパイプしたいと思います。

tar -cvf - /tmp/source-dir | lzip -o /media/my-usb/result.lz -

私は複数行のテキストを含むコマンドを出力するためにパイプを使用してきました。今、非常に大きな出力(例えば、tar非常に遅い圧縮命令の後に続く)を含む(高速)命令をパイプするとどうなりますか?tar出力が消費されるのを待ちますかlzip?それとも、できるだけ早くすべてをRAMに出力しますか?後者が真であれば、RAMが少ないシステムでは災害になります。

答え1

データプロデューサ(tar)がパイプに書きすぎようとして消費者(lzip)がすべてのデータを読み取る時間がない場合詰まった書かれた内容をlzip読む時間があるまで。tarパイプに関連する小さなバッファがありますが、そのサイズはおそらくtarほとんどのアーカイブより小さいでしょう。パイプがシステムRAMを満たす危険はありません。

「ブロック」は、単にtarライブラリ関数(またはそれに対応する関数)が呼び出されたときにデータがパイプバッファに渡されるまで呼び出しが返されないことを意味し、同じバッファからの読み込みが遅い場合は時間がかかることがありwrite()ます。lzip(実際にはより速いと仮定すると)スピードが遅くなり、睡眠の多い場所と比べるとこれを見るtopことができます。tarlziptarlzip

だからあなたはいいえ大量のRAMを満たすには、パイプを使用してください。これを行うには(必要に応じて)、pv大きなバッファ(ここではギガバイト)を使用して、途中で次のものを使用できます。

tar -cvf - /tmp/source-dir | pv --buffer-size 1G | lzip -o /media/my-usb/result.lz -

tarpvブロックされるたびにブロックされ続けます。pvバッファがいっぱいで書き込めないときにブロックされますlzip


逆の場合も同様に動作します。つまり、パイプの左側が遅く右が速い場合は、read()パイプから読み取るデータがあるまで右側のコンシューマがブロックされます。

これは(データI / O)パイプに参加しているプロセスを同期する唯一のものです。読取りと書込み(他の人が読んだり書くのを待っているときに時々ブロックされる)を除いて、互いに独立して実行されます。

答え2

牛に似た一種の栄養アスファルト持つ--lzipオプション「lzipによるアーカイブのフィルタリングそのため、次のように使用することもできます。

tar -cvf --lzip /media/my-usb/result.lz /tmp/source-dir

質問に答えてください。あなたの場合、システムはデフォルトのシステムバッファサイズを使用してパイプを正しく管理します。

関連情報