所定の場所にtarアーカイブを抽出します


14

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

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

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

tarを「その場で」抽出できる方法はありますか?アーカイブを抽出した後、アーカイブを保持する必要はないので、これを実行できるかどうか疑問に思っていました。

編集:アーカイブは既に送信されていることに注意する必要があります。別の方法で再送信しないようにしたいと思います。

回答:


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

これは次のように翻訳されます:

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

私は個人的に「rsync over ssh」を使用してものを転送します。なぜなら、接続が切断された場合でもものを転送し続けることができるからです:

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

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


編集した質問を参照してください
匿名

@チャーリー・サマヴィル:はい、そもそも重要な部分を省略しました。:)
アキラ

6

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

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

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

更新を編集

さて、これを削除してrsyncを再開することができない場合、これがどのように素晴らしいピクルスになるかがわかります。たぶん、選択的な抽出を試みて、tarから削除するでしょう。

選択的抽出物:

$ 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

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


編集した質問を参照してください
匿名

編集した回答をご覧ください...幸運を祈ります:-/
YuppieNetworking

編集してくれてありがとう。ファイルは実際には数字で名前が付けられているため、bashのクイックforループでうまくいくかもしれません。
匿名の

1
@Charlie Somerville:tarの最後に保存されているファイルから開始する必要がある場合があります。そうでない場合は、tarで新しいアーカイブを作成して終了する可能性があります。
アキラ

5

基本的に、必要なのは、ファイルをtarにパイプし、実行中にフロントを "lop"する可能性です。

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

解決策1

レベルの間接化は、すべての問題を解決します。最初にファイルを元に戻し、次に逆方向に読み取り(元のファイルを順方向に読み取ります)、逆方向のファイルの末尾を切り捨てます。

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

解決策2

別の方法は、ファイルをインプレースで小さなチャンクに分割し、それらのチャンクを抽出するときに削除することです。以下のコードのチャンクサイズは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行を再度実行して、抽出を再開します。

もちろん、これはすべて高級電圧です。最初にダミーアーカイブですべてが正常であることを確認する必要があります。なぜなら、間違え場合はデータをさようなら

最初の端末(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のすべてのデータが失われるので、データのバックアップがあることを確認してください。


0

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

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