14

cpio には、コピーアウト、コピーイン、パススルーの 3 つのモードがあることを知りました。

tar に対するコピーアウトおよびコピーインモードでの cpio の長所と短所は何だろうと思っていました。いつ cpio を使用し、いつ tar を使用するのが良いですか?

パススルー モードと cp での cpio に関する同様の質問。

よろしくお願いします!

4

3 に答える 3

-5

cpio が tar より優れているのはなぜですか? いくつかの理由。

  1. cpio はハード リンクを保持します。これは、バックアップに使用している場合に重要です。
  2. cpio には、煩わしいファイル名の長さの制限がありません。確かに、gnutar にはより長いファイル名を使用できるようにする「ハック」があります (実際の名前を格納する一時ファイルを作成します) が、本質的に非 gnu tar には移植できません。
  3. デフォルトでは、cpio はタイムスタンプを保持します
  4. スクリプトを作成する場合、コピーするファイルを明示的にリストする必要があるため、コピーするファイルとコピーしないファイルをより適切に制御できます。たとえば、次のうちどれが読みやすく理解しやすいですか?

    find . -type f -name '*.sh' -print | cpio -o | gzip >sh.cpio.gz
    

    または Solaris の場合:

    find . -type f -name '*.sh' -print >/tmp/includeme
    tar -cf - . -I /tmp/includeme | gzip >sh.tar.gz
    

    または gnutar を使用:

    find . -type f -name '*.sh' -print >/tmp/includeme
    tar -cf - . --files-from=/tmp/includeme | gzip >sh.tar.gz
    

    ここでいくつかの注意点があります。ファイルのリストが大きい場合、find を逆引用​​符で囲むことはできません。コマンドラインの長さがオーバーランします。中間ファイルを使用する必要があります。アクションが連続して実行されるため、個別の find コマンドと tar コマンドは本質的に遅くなります。

    ツリーを完全にパッケージ化し、いくつかのファイルを 1 つの tar に、残りのファイルを別の tar に入れたいという、より複雑なケースを考えてみましょう。

    find . -depth -print >/tmp/files
    egrep    '\.sh$' /tmp/files | cpio -o | gzip >with.cpio.gz
    egrep -v '\.sh$' /tmp/files | cpio -o | gzip >without.cpio.gz
    

    またはSolarisの下:

    find . -depth -print >/tmp/files
    egrep    '\.sh$' /tmp/files >/tmp/with
    tar -cf - . -I /tmp/with    | gzip >with.tar.gz
    tar -cf - .    /tmp/without | gzip >without.tar.gz
    ##          ^^-- no there's no missing argument here.  It's just empty that way
    

    または gnutar を使用:

    find . -depth -print >/tmp/files
    egrep    '\.sh$' /tmp/files >/tmp/with
    tar -cf - . -I /tmp/with    | gzip >with.tar.gz
    tar -cf - . -X /tmp/without | gzip >without.tar.gz
    

    繰り返しますが、いくつかの注意事項があります。個別の find コマンドと tar コマンドは、本質的に低速です。より多くの中間ファイルを作成すると、より混乱が生じます。gnutar は少しすっきりしていますが、コマンドライン オプションは本質的に互換性がありません!

  5. 混雑したネットワークを介して、あるマシンから別のマシンに大量のファイルを急いでコピーする必要がある場合は、複数の cpio を並行して実行できます。例えば:

    find . -depth -print >/tmp/files
    split /tmp/files
    for F in /tmp/files?? ; do
      cat $F | cpio -o | ssh destination "cd /target && cpio -idum" &
    done
    

    入力を均等なサイズの断片に分割できると役立つことに注意してください。これを行うために「npipe」というユーティリティを作成しました。npipe は stdin から行を読み取り、N 個の出力パイプを作成し、各行が消費されるたびにそれらに行を供給します。このようにして、最初のエントリが転送に 10 分かかった大きなファイルで、残りが転送に 2 分かかった小さなファイルだった場合、大きなファイルとその後ろにキューに入れられた別の数十の小さなファイルを待って停止することはありません。 . このようにして、ファイルのリストの行数やバイト数で厳密に分割するのではなく、必要に応じて分割することになります。同様の機能は、gnu-xargs の並列分岐機能で実現できますが、引数を標準入力にストリーミングする代わりにコマンドラインに配置する点が異なります。

    find . -depth -print >/tmp/files
    npipe -4 /tmp/files 'cpio -o | ssh destination "cd /target && cpio -idum"'
    

    これはどのように高速ですか?NFS を使用しないのはなぜですか? なぜ rsync を使わないのですか? NFS は本質的に非常に低速ですが、さらに重要なことは、1 つのツールの使用が本質的にシングル スレッドであることです。rsync はソース ツリーを読み取り、一度に 1 つのファイルを宛先ツリーに書き込みます。マルチ プロセッサ マシンを使用している場合 (当時、私はマシンごとに 16cpu を使用していました)、並列書き込みが非常に重要になりました。8GB ツリーのコピーを 30 分に短縮しました。それは 4.6MB/秒です! 100Mbit ネットワークは 5 ~ 10MB/秒を簡単に実行できるため、確かに遅いように聞こえますが、遅いのは inode の作成時間です。このツリーには簡単に 500,000 個のファイルがありました。したがって、i ノードの作成がボトルネックである場合は、その操作を並列化する必要がありました。比較すると、シングル スレッドでファイルをコピーするには 4 時間かかります。それは8倍速いです!

    これがより高速であった第 2 の理由は、並列 tcp パイプがあちこちで失われたパケットに対して脆弱ではないことです。パケットが失われたために 1 つのパイプが停止した場合、通常、他のパイプは影響を受けません。これがどの程度の違いを生んだかはよくわかりませんが、細かくマルチスレッド化されたカーネルの場合、アイドル状態のすべての CPU にワークロードを分散できるため、これもより効率的になります。

私の経験では、cpio は tar より全体的に優れているだけでなく、引数の移植性も高い (引数は cpio のバージョン間で変更されない!) が、一部のシステムでは見つからない場合があります (RedHat ではデフォルトでインストールされません)。ですが、Solaris にもデフォルトで gzip は付属していません。

于 2010-11-27T18:29:48.287 に答える