Bagaimana saya bisa menentukan apakah menjalankan tar akan menyebabkan disk terisi

22

Jika saya menjalankan tar -cvfdirektori ukuran 937MB untuk membuat salinan yang mudah diunduh dari struktur folder yang bersarang, apakah saya berisiko mengisi disk dengan df -houtput sebagai berikut :

/dev/xvda1            7.9G  3.6G  4.3G  46% /
tmpfs                 298M     0  298M   0% /dev/shm

Pertanyaan-pertanyaan Terkait:

  • Jika disk mungkin terisi, mengapa apa yang akan Linux (Amazon AMI) dan / atau tarlakukan di bawah tenda?
  • Bagaimana saya dapat secara akurat menentukan informasi ini sendiri tanpa bertanya lagi?
codecowboy
sumber
Saya tidak yakin apakah mungkin tanpa memproses arsip, tetapi Anda dapat bermain-main dengan --totalsopsi. Either way jika Anda mengisi disk Anda hanya dapat menghapus arsip, imho. Untuk memeriksa semua opsi yang tersedia, Anda dapat melewati tar --help.
UVV
4
Secara tangensial: jangan membuat tarfile sebagai root, persentase ruang tertentu pada disk disisihkan untuk root secara eksklusif, tepatnya untuk jenis "Saya telah mengisi disk dan sekarang saya tidak dapat login karena itu akan menulis. situasi bash_history atau apa pun ".
Ulrich Schwarz

Jawaban:

24

tar -c data_dir | wc -c tanpa kompresi

atau

tar -cz data_dir | wc -c dengan kompresi gzip

atau

tar -cj data_dir | wc -c dengan kompresi bzip2

akan mencetak ukuran arsip yang akan dibuat dalam byte, tanpa menulis ke disk. Anda kemudian dapat membandingkannya dengan jumlah ruang kosong pada perangkat target Anda.

Anda dapat memeriksa ukuran direktori data itu sendiri, jika asumsi dibuat tentang ukurannya, dengan perintah berikut:

du -h --max-depth=1 data_dir

Seperti yang sudah dijawab, tar menambahkan header ke setiap record dalam arsip dan juga mengumpulkan ukuran setiap record hingga kelipatan 512 byte (secara default). Akhir dari arsip ditandai oleh setidaknya dua catatan tanpa diisi berurutan. Jadi selalu terjadi bahwa Anda akan memiliki file tar terkompresi lebih besar dari file itu sendiri, jumlah file dan bagaimana mereka menyelaraskan ke batas 512 byte menentukan ruang ekstra yang digunakan.

Tentu saja, filesystem itu sendiri menggunakan ukuran blok yang mungkin lebih besar dari konten file individual jadi berhati-hatilah saat Anda membukanya, filesystem mungkin tidak dapat menampung banyak file kecil meskipun memiliki ruang bebas lebih besar dari ukuran tar!

https://en.wikipedia.org/wiki/Tar_(computing)#Format_details

FantasticJamieBurns
sumber
Terima kasih Jamie! Apa yang '- mysql' lakukan di sini? Apakah itu nama file Anda?
codecowboy
Baru saja mengubah itu ... itu adalah jalan ke direktori data Anda.
FantasticJamieBurns
1
Bukannya itu benar-benar penting, tetapi menggunakan kombinasi argumen -f -untuk tar adalah mubazir, karena Anda bisa mengabaikan -fargumen itu untuk menulis hasilnya ke stdout (yaitu tar -c data_dir).
6

Ukuran file tar Anda akan menjadi 937MB plus ukuran metadata yang diperlukan untuk setiap file atau direktori (512 byte per objek), dan padding ditambahkan untuk menyelaraskan file ke batas 512-byte.

Perhitungan yang sangat kasar memberi tahu kami bahwa salinan data Anda yang lain akan memberikan Anda 3.4GB gratis. Dalam 3.4GB kami memiliki ruang untuk sekitar 7 juta catatan metadata, dengan asumsi tidak ada padding, atau lebih sedikit jika Anda mengasumsikan rata-rata padding 256 byte per file. Jadi, jika Anda memiliki jutaan file dan direktori untuk ditampung, Anda mungkin mengalami masalah.

Anda dapat mengurangi masalah dengan

  • mengompresi dengan cepat dengan menggunakan opsi zatau juntuktar
  • melakukan hal itu tarsebagai pengguna biasa sehingga ruang yang disediakan pada /partisi tidak akan disentuh jika Anda kehabisan ruang.
Flup
sumber
2

tarsendiri dapat melaporkan ukuran arsipnya dengan --testopsi:

tar -cf - ./* | tar --totals -tvf -

Perintah di atas tidak menulis apa pun ke disk dan memiliki manfaat tambahan dari mendaftarkan masing-masing filesize masing-masing file yang terkandung dalam tarball. Menambahkan berbagai z/j/xzoperan ke kedua sisi |pipeakan menangani kompresi seperti yang Anda mau.

KELUARAN:

...
-rwxr-xr-x mikeserv/mikeserv         8 2014-03-13 20:58 ./somefile.sh
-rwxr-xr-x mikeserv/mikeserv        62 2014-03-13 20:53 ./somefile.txt
-rw-r--r-- mikeserv/mikeserv       574 2014-02-19 16:57 ./squash.sh
-rwxr-xr-x mikeserv/mikeserv        35 2014-01-28 17:25 ./ssh.shortcut
-rw-r--r-- mikeserv/mikeserv        51 2014-01-04 08:43 ./tab1.link
-rw-r--r-- mikeserv/mikeserv         0 2014-03-16 05:40 ./tee
-rw-r--r-- mikeserv/mikeserv         0 2014-04-08 10:00 ./typescript
-rw-r--r-- mikeserv/mikeserv       159 2014-02-26 18:32 ./vlc_out.sh
Total bytes read: 4300943360 (4.1GiB, 475MiB/s)

Tidak sepenuhnya yakin dengan tujuan Anda, tetapi jika ingin mengunduh tarball, ini mungkin lebih penting:

ssh you@host 'tar -cf - ./* | cat' | cat >./path/to/saved/local/tarball.tar

Atau hanya menyalin tar:

ssh you@host 'tar -cf - ./* | cat' | tar -C/path/to/download/tree/destination -vxf -
mikeserv
sumber
Alasan saya melakukan ini adalah karena saya percaya direktori yang dimaksud telah menyebabkan output dari df -i mencapai 99%. Saya ingin menyimpan salinan direktori untuk analisis lebih lanjut tetapi ingin membersihkan ruang
codecowboy
@codecowboy Dalam hal ini, Anda harus melakukan sesuatu seperti di atas terlebih dahulu. Kemudian akan tarmenyalin pohon ke disk lokal Anda dalam aliran tanpa menyimpan apa pun ke disk jarak jauh sama sekali, setelah itu Anda dapat menghapusnya dari host jarak jauh dan mengembalikannya nanti. Anda mungkin harus menambahkan -zuntuk kompresi seperti yang ditunjukkan goldilocks, untuk menghemat bandwidth transfer tengah.
mikeserv
@ TAFKA'goldilocks 'Tidak, karena ini 99% dari inode, bukan 99% dari ruang.
Gilles 'SO- berhenti bersikap jahat'
-ibenar maaf
goldilocks
@mikeserv baris pembuka Anda menyebutkan opsi --test tetapi Anda tampaknya tidak menggunakannya dalam perintah Anda yang segera mengikuti (menggunakan --totals)
codecowboy
2

Saya telah melakukan banyak penelitian tentang ini. Anda dapat melakukan tes pada file dengan jumlah kata tetapi itu tidak akan memberi Anda nomor nomor yang sama dengan a du -sb adir.

tar -tvOf afile.tar | wc -c

dumenghitung setiap direktori sebagai 4096 byte, dan tarmenghitung direktori sebagai 0 byte. Anda harus menambahkan 4096 ke setiap direktori:

$(( $(tar -tvOf afile.tar 2>&1 | grep '^d' | wc -l) * 4096)))

maka Anda harus menambahkan semua karakter. Untuk sesuatu yang terlihat seperti ini:

$(( $(tar -tvOf afile.tar 2>&1 | grep '^d' | wc -l) * 4096 + $(tar -xOf afile.tar | wc -c) ))

Saya tidak yakin apakah ini sempurna karena saya tidak mencoba file yang telah disentuh (file 0 byte) atau file yang memiliki 1 karakter. Ini akan membuat Anda lebih dekat.

tass6773
sumber
1

-cvftidak termasuk kompresi, melakukan hal itu pada folder ~ 1 GB akan menghasilkan file tar ~ 1 GB (jawaban Flub memiliki detail lebih lanjut tentang ukuran tambahan dalam file tar, tetapi perhatikan bahkan jika ada 10.000 file ini hanya 5 MB). Karena Anda memiliki 4+ GB gratis, tidak, Anda tidak akan mengisi partisi.

salinan yang dapat diunduh dengan mudah

Kebanyakan orang akan menganggap "lebih mudah" identik dengan "lebih kecil" dalam hal mengunduh, jadi Anda harus menggunakan beberapa kompresi di sini. bzip2harus sekarang-a-hari tersedia pada sistem w / tar, saya pikir, jadi termasuk jdalam switch Anda mungkin merupakan pilihan terbaik. z( gzip) mungkin bahkan lebih umum, dan ada kemungkinan lain (kurang di mana-mana) dengan squash lebih banyak.

Jika maksud Anda, apakah tarmenggunakan ruang disk tambahan untuk sementara dalam melakukan tugas, saya cukup yakin itu bukan karena beberapa alasan, satu karena tanggal kembali ke waktu ketika tape drive adalah bentuk penyimpanan utama, dan dua karena memiliki memiliki dekade untuk berkembang (dan saya yakin tidak perlu menggunakan ruang perantara sementara, bahkan jika kompresi terlibat).

goldilocks
sumber
0

Jika kecepatan penting dan kompresi tidak diperlukan, Anda dapat mengaitkan pembungkus syscall yang digunakan dengan tarmenggunakan LD_PRELOAD, untuk mengubah taruntuk menghitungnya bagi kami. Dengan mengimplementasikan kembali beberapa fungsi ini untuk memenuhi kebutuhan kita (menghitung ukuran data tar potensial), kita dapat menghilangkan banyak readdan writeyang dilakukan dalam operasi normal tar. Ini membuat tarlebih cepat karena tidak perlu konteks bolak-balik ke kernel di mana saja dekat sebanyak dan hanya statfile input / folder yang diminta harus dibaca dari disk daripada data file yang sebenarnya.

Kode di bawah meliputi implementasi dari close, read, dan writefungsi POSIX. Makro OUT_FDmengontrol deskriptor file mana yang kami harapkan taruntuk digunakan sebagai file output. Saat ini diatur ke stdout.

readdiubah menjadi hanya mengembalikan nilai keberhasilan countbyte alih-alih mengisi buf dengan data, mengingat bahwa data aktual tidak dibaca buf tidak akan berisi data yang valid untuk diteruskan ke kompresi, dan dengan demikian jika kompresi digunakan kami akan menghitung yang salah ukuran.

writediubah untuk menjumlahkan countbyte input ke dalam variabel global totaldan mengembalikan nilai keberhasilan countbyte hanya jika file deskriptor cocok OUT_FD, jika tidak maka akan memanggil wrapper asli yang diperoleh melalui dlsymuntuk melakukan syscall dengan nama yang sama.

closemasih melakukan preforms semua fungsionalitas aslinya, tetapi jika deskriptor file cocok dengan OUT_FD, ia tahu bahwa tarsudah selesai mencoba untuk menulis file tar, jadi totalangkanya adalah final dan mencetaknya ke stdout.

#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>
#include <string.h>

#define OUT_FD 1
uint64_t total = 0;
ssize_t (*original_write)(int, const void *, size_t) = NULL;
int (*original_close)(int) = NULL;
void print_total(void)
{
    printf("%" PRIu64 "\n", total);
}

int close(int fd)
{
    if(! original_close)
    {
        original_close = dlsym(RTLD_NEXT, "close");
    }
    if(fd == OUT_FD)
    {
        print_total();
    }
    return original_close(fd);
}

ssize_t read(int fd, void *buf, size_t count)
{
    return count;
}

ssize_t write(int fd, const void *buf, size_t count)
{
    if(!original_write)
    {
        original_write = dlsym(RTLD_NEXT, "write");
    }
    if(fd == OUT_FD)
    {
        total += count;
        return count;
    }
    return original_write(fd, buf, count);
}

Benchmark membandingkan solusi di mana akses disk baca dan semua syscalls operasi tar normal dilakukan terhadap LD_PRELOADsolusi.

$ time tar -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/ | wc -c
332308480
real    0m0.457s
user    0m0.064s
sys     0m0.772s
tarsize$ time ./tarsize.sh -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/
332308480
real    0m0.016s
user    0m0.004s
sys     0m0.008s

Kode di atas, skrip build dasar untuk membangun di atas sebagai pustaka bersama, dan skrip dengan " LD_PRELOADteknik" menggunakannya disediakan dalam repo: https://github.com/G4Vi/tarsize

Beberapa info tentang cara menggunakan LD_PRELOAD: https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/

G4Vi
sumber
Kode itu baik, jika berhasil, tetapi bisakah Anda menjelaskan apa fungsinya? Tolong jangan menanggapi dalam komentar; edit  jawaban Anda untuk membuatnya lebih jelas dan lebih lengkap.
G-Man Mengatakan 'Reinstate Monica'