web-dev-qa-db-ja.com

インプレース抽出tarアーカイブ

ここに少しジレンマがあります...

サーバーの1つから別のサーバーに約70GB相当のファイルを移動する必要があったので、それらをタール化​​してアーカイブを送信するのが最速の方法であると判断しました。

ただし、受信サーバーには、tarアーカイブを受信した後に5GBのスペースしか残っていません。

タールを「インプレース」で抽出する方法はありますか?解凍後はアーカイブを保存する必要がないので、保存できるのかと思っていました。

編集: アーカイブはすでに送信されているので、別の方法で再送信することは避けたいことに注意してください。

14
% tar czf - stuff_to_backup | ssh backupmachine tar xvzf -

これは次のように解釈されます。

  • 'stuff_to_backup'を標準入力にtarおよび圧縮します
  • ssh経由で「backupmachine」にログインします
  • 'backupmachine'で 'tar'を実行し、stdinから入ってくるものをuntarします

接続が切断された場合でも転送を続行できるため、個人的には「rsyncoverssh」を使用して転送します。

% rsync -ar --progress -e 'ssh' 'stuff_to_backup' user@backupmachine:/backup/

これにより、すべてが「stuff_to_backup」から「backupmachine」の「backup」フォルダに転送されます。接続が切断された場合は、コマンドを繰り返してください。 'stuff_to_backup'の一部のファイルが変更された場合は、その内容を繰り返してください。違いのみが転送されます。

11
akira

他のマシンにsshがある場合は、tarファイルを使用しない別の方法としてrsyncを使用することをお勧めします。

rsync -avPz /some/dir/ user@machine:/some/other/dir/

そして、先頭の/に注意してください

更新の編集

さて、これを削除してrsyncを再開できない場合、これがどのように優れたピクルスになったかがわかります。私はおそらく選択的な抽出を試み、タールから削除します。

選択的抽出物:

$ tar xvf googlecl-0.9.7.tar googlecl-0.9.7/README.txt
googlecl-0.9.7/README.txt

選択的削除:

$ tar --delete --file=googlecl-0.9.7.tar googlecl-0.9.7/README.txt

ただし、このためのスクリプトのコーディングには多くの時間を費やすようです...

6

基本的に、必要なのはファイルをtarにパイプし、進むにつれて前面を「lop」する可能性です。

StackOverflowで、誰かが 前のファイルを切り捨てる 方法を尋ねましたが、それは不可能のようです。ファイルの先頭を特別な方法でゼロで埋めて、ファイルが スパースファイル になるようにすることもできますが、これを行う方法がわかりません。ただし、ファイルの終わりを切り捨てることはできます。ただし、tarはアーカイブを逆方向ではなく順方向に読み取る必要があります。

ソリューション1

間接参照のレベルは、すべての問題を解決します。最初にファイルをインプレースで反転し、次にそれを逆方向に読み取り(これにより、元のファイルが順方向に読み取られます)、反転したファイルの終わりを切り捨てます。

ファイルの最初と最後をチャンクごとに交換するプログラム(c、pythonなど)を作成し、ファイルを一度に1チャンクずつ切り捨てながら、これらのチャンクをtarにパイプする必要があります。これがソリューション2の基礎であり、おそらく実装が簡単です。

ソリューション2

もう1つの方法は、 ファイルをその場で小さなチャンクに分割する 、次にそれらを抽出するときにそれらのチャンクを削除することです。以下のコードのチャンクサイズは1メガバイトで、必要に応じて調整してください。大きいほど高速ですが、分割時および抽出時により多くの中間スペースが必要になります。

ファイルarchive.tarを分割します:

archive="archive.tar"
chunkprefix="chunk_"
# 1-Mb chunks :
chunksize=1048576

totalsize=$(wc -c "$archive" | cut -d ' ' -f 1)
currentchunk=$(((totalsize-1)/chunksize))
while [ $currentchunk -ge 0 ]; do
    # Print current chunk number, so we know it is still running.
    echo -n "$currentchunk "
    offset=$((currentchunk*chunksize))
    # Copy end of $archive to new file
    tail -c +$((offset+1)) "$archive" > "$chunkprefix$currentchunk"
    # Chop end of $archive
    truncate -s $offset "$archive"
    currentchunk=$((currentchunk-1))
done

これらのファイルをtarにパイプします(2番目のターミナルにchunkprefix変数が必要であることに注意してください):

mkfifo fifo
# In one terminal :
(while true; do cat fifo; done) | tar -xf -
# In another terminal :
chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
    cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
    currentchunk=$((currentchunk+1))
done > fifo
# When second terminal has finished :
# flush caches to disk :
sync
# wait 5 minutes so we're sure tar has consumed everything from the fifo.
sleep 300
rm fifo
# And kill (ctrl-C) the tar command in the other terminal.

名前付きパイプ(mkfifo fifo)を使用するため、すべてのチャンクを一度にパイプする必要はありません。これは、スペースが非常に限られている場合に役立ちます。次の手順を実行できます。

  • たとえば、最後の10Gbチャンクを別のディスクに移動します。
  • まだ残っているチャンクから抽出を開始します。
  • while [ -e … ]; do cat "$chunk…; doneループが終了したとき(2番目の端末):
  • tarコマンドを停止しないでください。fifo(最初のターミナル)を削除しないでください。ただし、syncは実行できます。 、 念のため、
  • 完了していることがわかっている抽出ファイル(データがこれらのファイルの抽出を完了するのを待ってtarが停止しない)を別のディスクに移動します。
  • 残りのチャンクを元に戻し、
  • while [ -e … ]; do cat "$chunk…; done行を再度実行して、抽出を再開します。

もちろん、これはすべてhaute voltigeです。間違いを犯した場合はなので、最初にダミーアーカイブですべてが正常であることを確認する必要があります。それからさようならデータ

最初の端末(tar)が実際にFIFOの内容の処理を終了したかどうかはわかりません。したがって、必要に応じてこれを実行できますが、チャンクをシームレスに交換することはできません。別のディスク:

chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
    cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
    currentchunk=$((currentchunk+1))
done | tar -xf -

免責事項

これらすべてが機能するためには、シェル、テール、およびトランケートが64ビット整数を正しく処理する必要があることに注意してください(64ビットコンピューターやオペレーティングシステムは必要ありません)。私の場合はそうですが、これらの要件のないシステムで上記のスクリプトを実行すると、archive.tarのすべてのデータが失われます。

そして、それ以外の問題が発生した場合は、とにかくarchive.tar内のすべてのデータが失われるため、データのバックアップがあることを確認してください。

5

移動するオブジェクトファイルがある場合は、それらを削除してみてください。これにより、かなりのスペースを節約できます。

$ strip `find . -name "*.bin"`
0
kumar