Di tempat ekstrak arsip tar

14

Saya punya sedikit dilema di sini ...

Saya perlu memindahkan sekitar 70 GB nilai file dari satu server saya ke yang lain, jadi saya memutuskan bahwa menaruhnya dan mengirimkan arsip akan menjadi cara tercepat.

Namun, server penerima hanya memiliki 5 GB ruang tersisa setelah menerima arsip tar.

Apakah ada cara saya bisa mengekstrak tar 'di tempat'? Saya tidak perlu menyimpan arsip setelah diekstraksi, jadi saya bertanya-tanya apakah mungkin untuk melakukan ini.

Sunting: Perlu dicatat bahwa arsip telah dikirim, dan saya ingin menghindari mengirim ulang melalui metode yang berbeda.

pengecut anonim
sumber

Jawaban:

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

ini diterjemahkan menjadi:

  • tar dan kompres 'stuff_to_backup' ke stdout
  • masuk ke 'backupmachine' melalui ssh
  • jalankan 'tar' pada 'backupmachine' dan hapus hal-hal yang datang dari stdin

saya pribadi akan menggunakan 'rsync over ssh' untuk mentransfer barang-barang karena Anda dapat terus mentransfer barang-barang jika koneksi terputus:

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

yang akan mentransfer semuanya dari 'stuff_to_backup' ke folder 'backup' di 'backupmachine'. jika koneksi terputus, ulangi perintahnya. jika beberapa file dalam 'stuff_to_backup' berubah, ulangi hal-hal tersebut, hanya perbedaannya yang akan ditransfer.

akira
sumber
Lihat pertanyaan saya yang diedit
pengecut anonim
@Charlie Somerville: ya, Anda meninggalkan bagian penting di tempat pertama. :)
akira
6

Jika mesin lain memiliki ssh, saya akan merekomendasikan Anda rsync sebagai alternatif lain yang tidak menggunakan file tar:

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

Dan hati-hati dengan yang terdepan /

Edit pembaruan

Yah, saya melihat bagaimana ini sekarang acar yang baik jika Anda tidak dapat menghapusnya dan memulai kembali dengan rsync. Saya mungkin akan mencoba ekstrak selektif dan menghapus dari tar.

ekstrak selektif:

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

hapus selektif:

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

Namun, tampaknya Anda akan menghabiskan banyak waktu untuk menulis naskah untuk ...

YuppieNetworking
sumber
Lihat pertanyaan saya yang diedit
pengecut anonim
Lihat jawaban saya yang diedit ... semoga berhasil: - /
YuppieNetworking
Terima kasih atas hasil editnya. File-file tersebut sebenarnya dinamai dengan angka, jadi cepat untuk loop di bash mungkin bisa melakukan trik.
pengecut anonim
1
@Charlie Somerville: Anda mungkin harus mulai dengan file yang disimpan di ujung tar, jika tidak, Anda mungkin berakhir dengan tar membuat arsip baru ... jadi, hapus dulu file dari ujung tar.
akira
5

Pada dasarnya, yang Anda butuhkan adalah kemungkinan untuk mem-pipe file ke tar, dan "buka" bagian depan saat Anda menggunakannya.

Pada StackOverflow, seseorang bertanya bagaimana memotong file di depan , tetapi sepertinya itu tidak mungkin. Anda masih dapat mengisi awal file dengan nol dengan cara khusus sehingga file menjadi file yang jarang , tetapi saya tidak tahu bagaimana melakukan ini. Kami dapat memotong bagian akhir file. Tetapi tar perlu membaca arsip ke depan, bukan ke belakang.

Solusi 1

Tingkat tipuan menyelesaikan setiap masalah. Pertama-tama balikkan file di tempat, kemudian bacalah mundur (yang akan menghasilkan membaca file asli ke depan) dan memotong ujung file terbalik saat Anda pergi.

Anda harus menulis sebuah program (c, python, apa pun) untuk bertukar awal dan akhir file, chunk by chunk, dan kemudian pipa chunk ini ke tar sambil memotong file chunk sekaligus. Ini adalah dasar untuk solusi 2 yang mungkin lebih mudah diterapkan.

Solusi 2

Metode lain adalah dengan membagi file menjadi potongan-potongan kecil di tempat , lalu hapus potongan-potongan itu saat kita mengekstraknya. Kode di bawah ini memiliki ukuran chunk satu megabyte, sesuaikan tergantung kebutuhan Anda. Lebih besar lebih cepat tetapi akan membutuhkan lebih banyak ruang antara saat pemisahan dan selama ekstraksi.

Pisahkan file 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

Pipa file-file itu ke tar (perhatikan kita perlu variabel chunkprefix di terminal kedua):

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.

Karena kami menggunakan pipa bernama ( mkfifo fifo), Anda tidak harus mem-pipe semua chunks sekaligus. Ini bisa bermanfaat jika Anda benar-benar kekurangan ruang. Anda dapat mengikuti langkah-langkah berikut:

  • Pindahkan, ucapkan 10 gb potongan terakhir ke disk lain,
  • Mulai ekstraksi dengan potongan yang masih Anda miliki,
  • Ketika while [ -e … ]; do cat "$chunk…; doneloop telah selesai (terminal kedua):
  • JANGAN menghentikan tarperintah, JANGAN menghapus fifo (terminal pertama), tetapi Anda dapat menjalankan sync, untuk berjaga-jaga,
  • Pindahkan beberapa file yang diekstraksi yang Anda tahu sudah selesai (tar tidak terhenti menunggu data selesai mengekstraksi file-file ini) ke disk lain,
  • Pindahkan potongan yang tersisa kembali,
  • Lanjutkan ekstraksi dengan menjalankan while [ -e … ]; do cat "$chunk…; donegaris lagi.

Tentu saja ini semua haute voltige , Anda akan ingin memeriksa semuanya ok pada arsip dummy terlebih dahulu, karena jika Anda melakukan kesalahan maka selamat tinggal data .

Anda tidak akan pernah tahu apakah terminal pertama ( tar) telah benar-benar selesai memproses konten fifo, jadi jika Anda lebih suka Anda dapat menjalankan ini sebagai gantinya, tetapi Anda tidak akan memiliki kemungkinan untuk bertukar potongan tanpa cacat dengan disk lain:

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

Penolakan

Perhatikan bahwa agar semua ini berfungsi, shell, tail, dan truncate Anda harus menangani integer 64-bit dengan benar (Anda tidak memerlukan komputer 64-bit atau sistem operasi untuk itu). Milik saya, tetapi jika Anda menjalankan skrip di atas pada sistem tanpa persyaratan ini, Anda akan kehilangan semua data di archive.tar .

Dan dalam hal apa pun selain yang salah, Anda akan kehilangan semua data di archive.tar, jadi pastikan Anda memiliki cadangan data Anda.

Suzanne Dupéron
sumber
0

Jika Anda memiliki file objek yang akan dipindahkan, cobalah menghapusnya. Ini akan menghemat banyak ruang.

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