出力ファイルが/ dev / nullのときにtarがファイルの内容をスキップするように見えるのはなぜですか?


21

400 GiB以上のデータを含むディレクトリがあります。私はすべてのファイルがエラーなしで読めることを確認したかったので、私が考えた簡単な方法はにtarそれをすること/dev/nullでした。しかし、代わりに次の動作が見られます:

$ time tar cf /dev/null .

real    0m4.387s
user    0m3.462s
sys     0m0.185s
$ time tar cf - . > /dev/null

real    0m3.130s
user    0m3.091s
sys     0m0.035s
$ time tar cf - . | cat > /dev/null
^C

real    10m32.985s
user    0m1.942s
sys     0m33.764s

上記の3番目のコマンドは、かなり長い間実行された後、Ctrl+ によって強制的に停止されましたC。さらに、最初の2つのコマンドが機能している間、ストレージデバイスのアクティビティインジケータ.はほとんど常にアイドル状態でした。3番目のコマンドを使用すると、インジケータが常に点灯し、極度の忙しさを意味します。

そのためtar、その出力ファイルが/dev/nullであることがわかると、書き込みを/dev/null行うファイルハンドルを持つように直接開かれた場合tar、ファイル本文はスキップされたように見えます。(vオプションを追加tarすると、tar「赤」のディレクトリ内のすべてのファイルが印刷されます。)

なぜこれがそうなのだろうか?何らかの最適化ですか?はいの場合、なぜtarそのような特別な場合にそのような疑わしい最適化をしたいのでしょうか?

Linux 4.14.105 amd64でGNU tar 1.26とglibc 2.27を使用しています。


7
実用的な代替手段として、のようなものを検討してくださいfind . -type f -exec shasum -a256 -b '{}' +実際にすべてのデータを読み取ってチェックサムするだけでなく、出力を保存する場合は、後で再実行してファイルの内容が変更されていないことを確認できます。
イルマリカロネン

物事を測定するためにも使用できますpvtar -cf - | pv >/dev/null。それは問題を回避し、進捗情報(さまざまなpvオプション)を提供します
xenoid

GNU tarのよく知られているミス機能を見つけました。gtar -cf /dev/zero ...好きなものを取得するために使用します。
シリー

回答:


25

それ 文書化された最適化です:

アーカイブがに作成されているとき/dev/null、GNU tarは入出力操作を最小限に抑えようとします。AmandaバックアップシステムをGNU tarで使用する場合、この機能を使用する初期サイズ設定パスがあります。


4
ああ、これはインストールしたマニュアルページには記載されていませんでした。info tar代わりに試してみるべきだった...
ルスラン

9
彼らは本当にそれは、彼らがいないだと事実上のバグですが、同期の男&情報ページを維持する必要があります
Xen2050

9
@RuslanほとんどのGNUユーティリティでは、manページには簡単な要約のみが含まれています。基本的に、何かを行うオプションがあるがオプションの名前を覚えていないことを覚えている場合にのみ十分です。完全なドキュメントは、manページにうまく翻訳されない形式でありinfo、ブラウザでHTMLとして、またはHTMLとして入手できます。
ジル「SO-悪であるのをやめる」


8

これは、さまざまなプログラムで発生する可能性があります。たとえば、使用したときに一度しかその動作をしcp file /dev/nullませんでした。ディスク読み取り速度の推定値を取得する代わりに、数ミリ秒後にコマンドが返されました。

私の記憶では、これはSolarisまたはAIXでのことでしたが、原則はあらゆる種類のunix-yシステムに適用されます。

昔は、プログラムがファイルをどこかにコピーしたとき、readディスク(またはファイル記述子が参照するもの)からメモリにデータを取得する呼び出し(read戻り時にすべてが存在することを保証)とwrite呼び出しを交互に行いました。(メモリのチャンクを取得し、コンテンツを宛先に送信します)。

ただし、同じことを実現するための少なくとも2つの新しい方法があります。

  • Linuxにはシステムコールcopy_file_range(他のUNIXにはまったく移植性がない)とsendfile(多少移植性があります。当初はネットワークにファイルを送信することを目的としていたが、現在は任意の宛先を使用できます)。転送を最適化することを目的としています。プログラムがそれらのいずれかを使用する場合、カーネルがターゲットを認識し/dev/null、システムコールをノーオペレーションに変えることは容易に想像できます

  • プログラムはのmmap代わりにファイルの内容を取得するために使用できますread。これは基本的に、「システムコールが戻るときにデータがあることを確認する」のではなく、「メモリのチャンクにアクセスするときにデータがあることを確認する」ことを意味します。したがって、プログラムmmapはソースファイルwriteを取得し、マップされたメモリのそのチャンクを呼び出すことができます。ただし、書き込み/dev/nullは書き込まれたデータにアクセスする必要がないため、「データがあることを確認する」条件はトリガーされず、ファイルも読み込まれません。

GNU tarは任意の使用、およびわからない場合はこれは、これら2つのメカニズムで、それはそれはへの書き込みだ検出したとき/dev/null、彼らは任意のプログラムは、理由だ読み出し速度をチェックするために使用する場合、使用して実行されなければならない| cat > /dev/null代わりに> /dev/null-なぜと| cat > /dev/nullすべきことを避ける他のすべての場合で。


GNU tar情報ページ(他の回答を参照)の意味するところは、このための特別なモードがあり、おそらくファイルを開かずに統計するだけだと思います。実際tar cf /dev/null foo*、いくつかのファイルを確認したところ、newfstatat(..., AT_SYMLINK_NOFOLLOW)システムコールだけでopen()、atimeが更新されることさえありません。ただし、特別に検出することなくこれが発生する可能性のあるメカニズムを説明するための+1
ピーターコーデス

mmapの説明は、「書き込まれたデータにアクセスする」のではなく、「読み込まれたデータにアクセスする」と表示する必要がありますか?
ウェインコンラッド

splice(2)Linux も参照してください。実際には、交換するcat > /dev/nullpv -q > /dev/null(これは用途splice()そうなオーバーヘッドを削減するLinuxの場合)。あるいはdd bs=65536 skip=9999999999 2> /dev/null、またはwc -c > /dev/nullあるいはtail -c1 > /dev/null...
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.