Katakanlah saya memiliki file 80GB /root/bigfile
pada sistem 100GB dan ingin meletakkan file ini dalam arsip /root/bigarchive.tar
Saya jelas perlu menghapus file ini pada saat yang sama ketika itu ditambahkan dalam arsip. Karena itu pertanyaan saya:
Bagaimana cara menghapus file pada saat yang sama ketika itu ditambahkan dalam arsip?
tar
zip
compression
gzip
pengguna123456
sumber
sumber
Arsip tar terkompresi dari file tunggal terdiri dari header, file, dan pad trailing. Jadi masalah utama Anda adalah bagaimana menambahkan 512 byte header ke awal file Anda. Anda bisa mulai dengan membuat hasil yang diinginkan hanya dengan tajuk:
Kemudian salin 10G pertama file Anda. Untuk simpel, kami asumsikan dd Anda dapat membaca / menulis 1Gib sekaligus:
Kami sekarang membatalkan alokasi data yang disalin dari file asli:
Ini menggantikan data dengan nol jarang yang tidak memakan ruang pada sistem file. Lanjutkan dengan cara ini, menambahkan a
skip=10
ke yang berikutnyadd
, dan kemudian menambahkanfallocate
offset mulai ke-o 10GiB
. Di bagian paling akhir tambahkan beberapa karakter nul untuk melengkapi file tar akhir.Jika filesystem Anda tidak mendukung,
fallocate
Anda dapat melakukan hal serupa, tetapi mulai di akhir file. Pertama salin 10Gibytes terakhir dari file ke file perantara yang disebut, katakanlahpart8
,. Kemudian gunakantruncate
perintah untuk mengurangi ukuran file asli. Lanjutkan dengan cara yang sama sampai Anda memiliki 8 file masing-masing 10Gibyte. Anda kemudian dapat menggabungkan tajuk danpart1
untukbigarchive.tar
, lalu menghapuspart1
, dan kemudian menyatukanpart2
dan menghapusnya, dan seterusnya.sumber
Menghapus file tidak selalu melakukan apa yang Anda pikirkan. Itu sebabnya dalam sistem mirip UNIX, pemanggilan sistem dipanggil
unlink
dan tidakdelete
. Dari halaman manual:Akibatnya, selama kompresor data / pengarsipan membaca dari file, file itu tetap ada, menempati ruang dalam sistem file.
sumber
Mengingat konteksnya, saya akan menafsirkan pertanyaan ini sebagai:
Cara menghapus data dari disk segera setelah dibaca, sebelum file lengkap telah dibaca, sehingga ada cukup ruang untuk file yang diubah.
Transformasi dapat berupa apa pun yang ingin Anda lakukan dengan data: mengompresi, mengenkripsi, dll.
Jawabannya adalah ini:
Singkatnya: baca data, lemparkan ke gzip (atau apa pun yang ingin Anda lakukan dengannya), buffer outputnya sehingga kami yakin akan membaca lebih banyak daripada yang kami tulis, dan menulisnya kembali ke file. Ini adalah versi yang lebih cantik dan menampilkan keluaran saat berjalan:
Saya akan melewatinya, baris demi baris:
cat "$file"
membaca file yang ingin Anda kompres. Ini adalah penggunaan cat (UUOC) yang tidak berguna karena bagian selanjutnya, pv, juga dapat membaca file, tetapi saya menemukan ini lebih cantik.Ini menyalurkannya ke
pv
yang menunjukkan informasi kemajuan (-cN
memberi tahu 'gunakan semacam [c] ursor' dan beri nama [N]).Itu pipa
gzip
yang jelas melakukan kompresi (membaca dari stdin, keluaran ke stdout).Itu pipa ke yang lain
pv
(tampilan pipa).Pipa itu menjadi
dd bs=$buffer iflag=fullblock
. The$buffer
variabel adalah angka, sesuatu seperti 50 megabyte. Namun berapa banyak RAM yang ingin Anda dedikasikan untuk penanganan file Anda secara aman (sebagai titik data, buffer 50MB untuk file 2GB baik-baik saja). Theiflag=fullblock
memberitahudd
untuk membaca hingga$buffer
byte sebelum pipa melalui. Pada awalnya, gzip akan menulis header, jadi output gzip akan mendarat didd
baris ini . Kemudiandd
akan menunggu hingga memiliki cukup data sebelum disalurkan, sehingga input dapat dibaca lebih lanjut. Selain itu, jika Anda memiliki bagian yang tidak dapat dikompresi, file output mungkin lebih besar dari file input. Buffer ini memastikan bahwa, hingga$buffer
byte, ini bukan masalah.Kemudian kita pergi ke jalur tampilan pipa lain, dan akhirnya ke
dd
jalur output kami . Baris ini memilikiof
(file output) danconv=notrunc
ditentukan, di mananotrunc
memberitahudd
untuk tidak memotong (menghapus) file output sebelum menulis. Jadi, jika Anda memiliki 500 byteA
dan Anda menulis 3 byteB
, file tersebut akanBBBAAAAA...
(bukannya diganti olehBBB
).Saya tidak menutupi
2>/dev/null
bagian - bagiannya, dan itu tidak perlu. Mereka hanya merapikan output sedikit dengan menekandd
pesan "Saya sudah selesai dan menulis ini banyak byte". Garis miring terbalik pada akhir setiap baris (\
) membuat bash memperlakukan semuanya sebagai satu perintah besar yang saling menyambungkan satu sama lain.Berikut ini skrip lengkap untuk memudahkan penggunaan. Secara anekdot, saya meletakkannya di folder bernama 'gz-in-place'. Saya kemudian menyadari akronim yang saya buat: GZIP: gnu zip in-place. Jadi dengan ini saya hadir, GZIP.sh:
Saya merasa ingin menambahkan garis buffering lain sebelum gzip, untuk mencegahnya menulis terlalu jauh ketika
dd
garis buffering memancar, tetapi dengan hanya buffer 50MiB dan/dev/urandom
data 1900MB , sepertinya sudah berfungsi juga (md5sum cocok setelah dekompresi). Rasio yang cukup bagus untuk saya.Peningkatan lainnya adalah deteksi tulisan yang terlalu jauh, tetapi saya tidak melihat cara melakukannya tanpa menghilangkan keindahan benda itu dan menciptakan banyak kerumitan. Pada titik itu, Anda mungkin juga membuatnya menjadi program python sepenuhnya yang melakukan semuanya dengan benar (dengan failafes untuk mencegah kerusakan data).
sumber