Come posso determinare se l'esecuzione di tar causerà il riempimento del disco


22

Se corro tar -cvfsu una directory di dimensioni 937 MB per creare una copia facilmente scaricabile di una struttura di cartelle profondamente annidata, rischio di riempire il disco dato il seguente df -houtput:

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

Domande correlate:

  • Se il disco potrebbe riempirsi, perché, ad esempio, cosa farà Linux (Amazon AMI) e / o tarcosa farà sotto il cofano?
  • Come posso determinare con precisione queste informazioni da solo senza chiedere di nuovo?

Non sono sicuro che sia possibile senza elaborare l'archivio, ma puoi giocare con l' --totalsopzione. In ogni caso, se riempi il disco, puoi semplicemente eliminare l'archivio, imho. Per verificare tutte le opzioni disponibili è possibile passare attraverso tar --help.
UVV,

4
Tangenzialmente: non creare il tarfile come root, una certa percentuale di spazio sul disco è riservata esclusivamente a root, esattamente per il tipo di "Ho riempito il disco e ora non riesco ad accedere perché sarebbe scritto. bash_history o qualunque altra situazione.
Ulrich Schwarz,

Risposte:


24

tar -c data_dir | wc -c senza compressione

o

tar -cz data_dir | wc -c con compressione gzip

o

tar -cj data_dir | wc -c con compressione bzip2

stamperà la dimensione dell'archivio che verrebbe creato in byte, senza scrivere sul disco. È quindi possibile confrontarlo con la quantità di spazio libero sul dispositivo di destinazione.

È possibile controllare la dimensione della directory dei dati stessa, nel caso in cui sia stata fatta un'ipotesi errata sulla sua dimensione, con il seguente comando:

du -h --max-depth=1 data_dir

Come già risposto, tar aggiunge un'intestazione a ciascun record nell'archivio e inoltre arrotonda le dimensioni di ciascun record a un multiplo di 512 byte (per impostazione predefinita). La fine di un archivio è contrassegnata da almeno due record consecutivi a riempimento zero. Quindi è sempre il caso che tu abbia un file tar non compresso più grande dei file stessi, il numero di file e il modo in cui si allineano ai confini di 512 byte determina lo spazio extra utilizzato.

Ovviamente, i file system stessi usano dimensioni di blocco che forse sono più grandi del contenuto di un singolo file, quindi fai attenzione a dove non lo fai, il file system potrebbe non essere in grado di contenere molti file di piccole dimensioni anche se ha spazio libero maggiore della dimensione del tar!

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


Grazie Jamie! Cosa sta facendo "- mysql"? È il tuo nome file?
codecowboy,

Ho appena cambiato questo ... è il percorso della tua directory di dati.
FantasticJamieBurns

1
Non che sia davvero importante, ma usare la combinazione di argomenti -f -per tar è ridondante, poiché puoi semplicemente tralasciare del -ftutto l' argomento per scrivere il risultato su stdout (cioè tar -c data_dir).

6

La dimensione del tuo file tar sarà 937 MB più la dimensione dei metadati necessari per ogni file o directory (512 byte per oggetto) e il riempimento aggiunto per allineare i file a un limite di 512 byte.

Un calcolo molto approssimativo ci dice che un'altra copia dei tuoi dati ti lascerà con 3,4 GB gratuiti. In 3,4 GB abbiamo spazio per circa 7 milioni di record di metadati, supponendo che non ci sia alcun riempimento, o meno se si assume una media di 256 byte di riempimento per file. Quindi se hai milioni di file e directory da tarare, potresti incorrere in problemi.

Potresti mitigare il problema

  • comprimere al volo usando le opzioni zo jpertar
  • facendo tarcome un normale utente in modo che lo spazio riservato sulla /partizione non venga toccato se si esaurisce lo spazio.

2

tarstesso può riferire sulla dimensione dei suoi archivi con l' --testopzione:

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

Il comando sopra non scrive nulla sul disco e ha l'ulteriore vantaggio di elencare le singole dimensioni di ciascun file contenuto nel tarball. Aggiungendo i vari z/j/xzoperandi su entrambi i lati, la |pipecompressione verrà gestita come farai tu.

PRODUZIONE:

...
-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)

Non del tutto sicuro del tuo scopo, ma se si tratta di scaricare il tarball, questo potrebbe essere più al punto:

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

O semplicemente copiare con tar:

ssh you@host 'tar -cf - ./* | cat' | tar -C/path/to/download/tree/destination -vxf -

Il motivo per cui lo sto facendo è che credo che la directory in questione abbia fatto sì che l'output di df -i raggiungesse il 99%. Voglio conservare una copia della directory per ulteriori analisi, ma desidero liberare lo spazio
codecowboy,

@codecowboy In tal caso, dovresti assolutamente fare qualcosa di simile prima. Sarà tarquindi copiare l'albero sul disco locale in un flusso senza salvare nulla al disco remoto a tutti, dopo di che è possibile eliminarlo dall'host remoto e ripristinare in un secondo momento. Probabilmente dovresti aggiungere la -zcompressione come sottolinea il goldilocks, per risparmiare sulla larghezza di banda a metà trasferimento.
Mikeserv,

@ TAFKA'goldilocks 'No, perché è il 99% degli inode, non il 99% dello spazio.
Gilles 'SO- smetti di essere malvagio' il

-igiusto, scusa!
Riccioli d'oro

@mikeserv la tua linea di apertura menziona l'opzione --test ma non sembri usarla nel tuo comando che segue immediatamente (usa --totals)
codecowboy

2

Ho fatto molte ricerche su questo. Puoi fare un test sul file con un conteggio parole ma non ti darà lo stesso numero numerico di a du -sb adir.

tar -tvOf afile.tar | wc -c

duconta ogni directory come 4096 byte e tarconta le directory come 0 byte. Devi aggiungere 4096 a ciascuna directory:

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

allora devi aggiungere tutti i personaggi. Per qualcosa che assomiglia a questo:

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

Non sono sicuro che sia perfetto poiché non ho provato file toccati (file di 0 byte) o file con 1 carattere. Questo dovrebbe avvicinarti.


1

-cvfnon include alcuna compressione, quindi farlo su una cartella di ~ 1 GB si tradurrà in un file tar di ~ 1 GB (la risposta di Flub ha maggiori dettagli sulla dimensione aggiuntiva nel file tar, ma nota anche se ci sono 10.000 file questo è solo 5 MB). Dato che hai 4+ GB gratuiti, no non riempirai la partizione.

una copia facilmente scaricabile

La maggior parte delle persone considererebbe "più facile" sinonimo di "più piccolo" in termini di download, quindi è necessario utilizzare un po 'di compressione qui. bzip2ora dovrebbe essere disponibile su qualsiasi sistema con tar, penso, inclusoj nei tuoi switch è probabilmente la scelta migliore. z( gzip) è forse ancora più comune e ci sono altre (meno onnipresenti) possibilità con più zucca.

Se intendi, tarutilizza temporaneamente spazio su disco aggiuntivo nell'esecuzione dell'attività, sono abbastanza sicuro che non lo sia per alcuni motivi, uno dei quali risale a un'epoca in cui le unità nastro erano una forma di memoria principale e due lo sono ha avuto decenni di evoluzione (e sono certo che non è necessario utilizzare uno spazio intermedio temporaneo, anche se è implicata la compressione).


0

Se la velocità è importante e la compressione non è necessaria, è possibile agganciare i wrapper syscall utilizzati tarutilizzando LD_PRELOAD, per modificare tarper calcolarlo per noi. Reimplementando alcune di queste funzioni per soddisfare le nostre esigenze (calcolando la dimensione dei potenziali dati di catrame di output), siamo in grado di eliminare molte reade writeche vengono eseguite nel normale funzionamento di tar. Questo fatar molto più veloce in quanto non ha bisogno di passare da un contesto all'altro nel kernel in qualsiasi punto vicino e solo il statfile / le cartelle di input richiesto deve essere letto dal disco invece dei dati del file effettivo.

Il codice sotto include implementazioni dei close, reade writefunzioni POSIX. La macro OUT_FDcontrolla quale descrittore di file ci aspettiamotar di utilizzare come file di output. Attualmente è impostato su stdout.

readè stato modificato per restituire semplicemente il valore di successo dei countbyte invece di riempire buf con i dati, dato che i dati effettivi non sono stati letti buf non conterrebbero dati validi per il passaggio alla compressione, quindi se si utilizzava la compressione calcoleremmo un errore dimensione.

writeè stato modificato per sommare i countbyte di input nella variabile globale totale restituire il valore di successo dei countbyte solo se il descrittore di file corrisponde OUT_FD, altrimenti chiama il wrapper originale acquisito tramitedlsym per eseguire la syscall con lo stesso nome.

closepreforma ancora tutte le sue funzionalità originali, ma se il descrittore di file corrisponde a OUT_FD, sa che tarsi tenta di scrivere un file tar, quindi il totalnumero è definitivo e lo stampa su 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 confrontando una soluzione in cui l'accesso al disco di lettura e tutte le syscall della normale operazione tar vengono eseguiti rispetto alla LD_PRELOADsoluzione.

$ 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

Il codice sopra, uno script di compilazione di base per creare quanto sopra come libreria condivisa e uno script con la " LD_PRELOADtecnica" che lo utilizza viene fornito nel repository: https://github.com/G4Vi/tarsize

Alcune informazioni sull'uso di LD_PRELOAD: https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/


Il codice è buono, se funziona, ma puoi descriverlo ? Si prega di non rispondere nei commenti; modifica la  tua risposta per renderla più chiara e completa.
G-Man dice "Reinstate Monica" il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.