Wie kann ich feststellen, ob durch das Ausführen von tar die Festplatte voll wird?

22

Wenn ich tar -cvfein Verzeichnis mit einer Größe von 937 MB verwende, um eine einfach herunterladbare Kopie einer tief verschachtelten Ordnerstruktur zu erstellen, riskiere ich, den Datenträger mit der folgenden df -hAusgabe zu füllen :

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

Verwandte Fragen:

  • Wenn die Festplatte voll sein könnte, warum wird Linux (Amazon AMI) und / oder tarwas unter der Haube tun?
  • Wie kann ich diese Informationen selbst genau bestimmen, ohne erneut zu fragen?
Codecowboy
quelle
Ich bin nicht sicher, ob es möglich ist, ohne das Archiv zu bearbeiten, aber Sie können mit der --totalsOption herumspielen. In beiden Fällen können Sie das Archiv einfach löschen, wenn Sie die Festplatte voll haben. Um alle verfügbaren Optionen zu überprüfen, können Sie durchgehen tar --help.
UVV
4
Tangential: Erstellen Sie die Tarfile nicht als root, ein bestimmter Prozentsatz des Speicherplatzes auf der Festplatte ist ausschließlich für root reserviert, genau für die Art von "Ich habe die Festplatte gefüllt und kann mich jetzt nicht anmelden, da dies schreiben würde. bash_history oder was auch immer.
Ulrich Schwarz

Antworten:

24

tar -c data_dir | wc -c ohne Kompression

oder

tar -cz data_dir | wc -c mit Gzip-Komprimierung

oder

tar -cj data_dir | wc -c mit bzip2 Komprimierung

Gibt die Größe des zu erstellenden Archivs in Byte aus, ohne auf die Festplatte zu schreiben. Sie können dies dann mit der Menge an freiem Speicherplatz auf Ihrem Zielgerät vergleichen.

Mit dem folgenden Befehl können Sie die Größe des Datenverzeichnisses selbst überprüfen, falls eine falsche Annahme über seine Größe gemacht wurde:

du -h --max-depth=1 data_dir

Wie bereits beantwortet, fügt tar jedem Datensatz im Archiv einen Header hinzu und rundet die Größe jedes Datensatzes auf ein Vielfaches von 512 Bytes auf (Standardeinstellung). Das Ende eines Archivs ist durch mindestens zwei aufeinanderfolgende, mit Nullen gefüllte Datensätze gekennzeichnet. Es ist also immer der Fall, dass Sie eine unkomprimierte TAR-Datei haben, die größer ist als die Dateien selbst. Die Anzahl der Dateien und die Ausrichtung an 512-Byte-Grenzen bestimmen den zusätzlichen verwendeten Speicherplatz.

Natürlich verwenden Dateisysteme selbst Blockgrößen, die möglicherweise größer als der Inhalt einer einzelnen Datei sind. Seien Sie also vorsichtig, wenn Sie diese entpacken. Das Dateisystem kann möglicherweise nicht viele kleine Dateien aufnehmen, obwohl der freie Speicherplatz größer als die Teergröße ist!

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

FantasticJamieBurns
quelle
Danke Jamie! Was macht '- mysql' hier? Ist das dein Dateiname?
Codecowboy
Nur geändert, dass ... es der Pfad zu Ihrem Datenverzeichnis ist.
FantasticJamieBurns
1
Nicht, dass es wirklich wichtig wäre, aber die Verwendung der Argumentkombination -f -für tar ist überflüssig, da Sie das -fArgument einfach ganz weglassen können, um das Ergebnis in stdout (ie tar -c data_dir) zu schreiben .
6

Die Größe Ihrer TAR-Datei beträgt 937 MB plus der Größe der für jede Datei oder jedes Verzeichnis erforderlichen Metadaten (512 Byte pro Objekt). Außerdem wird eine Auffüllung hinzugefügt, um Dateien an einer 512-Byte-Grenze auszurichten.

Eine sehr grobe Berechnung zeigt uns, dass eine weitere Kopie Ihrer Daten 3,4 GB frei lässt. In 3,4 GB haben wir Platz für etwa 7 Millionen Metadatensätze, vorausgesetzt, dass keine Auffüllung erfolgt, oder weniger, wenn Sie von einer durchschnittlichen Auffüllung von 256 Byte pro Datei ausgehen. Wenn Sie also Millionen von Dateien und Verzeichnissen zu tar haben, können Probleme auftreten.

Sie könnten das Problem abmildern, indem Sie

  • Komprimieren im laufenden Betrieb mit den Optionen zoder jbistar
  • Führen Sie dies tarals normaler Benutzer aus, damit der reservierte Speicherplatz auf der /Partition nicht berührt wird, wenn Ihnen der Speicherplatz ausgeht.
Flup
quelle
2

tarselbst kann über die Größe seiner Archive berichten mit der --testOption:

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

Der obige Befehl schreibt nichts auf die Festplatte und hat den zusätzlichen Vorteil, dass die einzelnen Dateigrößen jeder im Tarball enthaltenen Datei aufgelistet werden. Das Hinzufügen der verschiedenen z/j/xzOperanden zu beiden Seiten des |pipeBefehls behandelt die Komprimierung wie gewünscht.

AUSGABE:

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

Sie sind sich Ihres Zwecks nicht ganz sicher, aber wenn es darum geht, den Tarball herunterzuladen, ist dies möglicherweise der springende Punkt:

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

Oder einfach kopieren mit tar:

ssh you@host 'tar -cf - ./* | cat' | tar -C/path/to/download/tree/destination -vxf -
mikeserv
quelle
Der Grund, warum ich das tue, ist, dass ich glaube, dass das fragliche Verzeichnis die Ausgabe von df -i auf 99% gebracht hat. Ich möchte eine Kopie des Verzeichnisses zur weiteren Analyse aufbewahren, aber den Speicherplatz
freimachen
@codecowboy In diesem Fall solltest du auf jeden Fall zuerst so etwas wie oben machen. tarAnschließend wird der Baum in einem Stream auf Ihre lokale Festplatte kopiert, ohne dass etwas auf der Remote-Festplatte gespeichert wird. Anschließend können Sie ihn vom Remote-Host löschen und später wiederherstellen. Sie sollten wahrscheinlich -zfür die Komprimierung hinzufügen, wie Goldlöckchen darauf hinweist, um Bandbreite bei der Übertragung zu sparen.
mikeserv
@ TAFKA'goldilocks 'Nein, denn es sind 99% der Inodes und nicht 99% des Speicherplatzes.
Gilles 'SO- hör auf böse zu sein'
-irichtig, sorry!
Goldlöckchen
@mikeserv Ihre Eröffnungszeile erwähnt die Option --test, aber Sie scheinen sie in Ihrem unmittelbar folgenden Befehl nicht zu verwenden (es verwendet --totals)
codecowboy
2

Ich habe viel darüber recherchiert. Sie können die Datei mit einer Wortzahl testen, aber es wird Ihnen nicht die gleiche Nummer wie a angezeigt du -sb adir.

tar -tvOf afile.tar | wc -c

duzählt jedes Verzeichnis als 4096 Bytes und tarVerzeichnisse als 0 Bytes. Sie müssen jedem Verzeichnis 4096 hinzufügen:

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

dann müssen Sie alle Zeichen hinzufügen. Für etwas, das so aussieht:

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

Ich bin mir nicht sicher, ob dies perfekt ist, da ich keine Dateien ausprobiert habe, die berührt wurden (Dateien mit 0 Bytes) oder Dateien mit 1 Zeichen. Das sollte dich näher bringen.

tass6773
quelle
1

-cvfBeinhaltet keine Komprimierung. Wenn Sie dies in einem ~ 1 GB-Ordner tun, erhalten Sie eine ~ 1 GB-TAR-Datei (die Antwort von Flub enthält weitere Informationen zur zusätzlichen Größe in der TAR-Datei. Beachten Sie jedoch, dass dies nur bei 10.000 Dateien der Fall ist 5 MB). Da Sie mehr als 4 GB frei haben, werden Sie die Partition nicht füllen.

eine leicht herunterladbare Kopie

Die meisten Leute würden das Herunterladen als "einfacher" und als "kleiner" bezeichnen, daher sollten Sie hier eine gewisse Komprimierung verwenden. bzip2Sollte nun ein Tag auf jedem System mit Teer verfügbar sein, denke ich, jist es wahrscheinlich die beste Wahl , dies in Ihre Switches aufzunehmen. z( gzip) ist vielleicht noch häufiger und es gibt andere (weniger allgegenwärtige) Möglichkeiten mit mehr Kürbis.

Wenn Sie meinen, für die tarAusführung der Aufgabe wird vorübergehend zusätzlicher Speicherplatz benötigt. Ich bin mir ziemlich sicher, dass dies aus mehreren Gründen nicht der Fall ist. Einer stammt aus einer Zeit, als Bandlaufwerke eine Form des Primärspeichers waren und der andere Es mussten sich Jahrzehnte entwickeln (und ich bin sicher, dass es nicht notwendig ist, temporären Zwischenraum zu verwenden, auch wenn es um Komprimierung geht).

Goldlöckchen
quelle
0

Wenn Geschwindigkeit wichtig ist und keine Komprimierung erforderlich ist, können Sie die verwendeten Syscall-Wrapper tarmit LD_PRELOAD, ändern tar, um sie für uns zu berechnen. Durch einige dieser Funktionen neu implementieren unsere Bedürfnisse anzupassen (die Größe der möglichen Ausgangs tar Daten Berechnung), sind wir viel beseitigen können readund writedass im Normalbetrieb von ausgeführt tar. Dies macht es tarviel schneller, da der Kontext nicht annähernd so schnell in den Kernel gewechselt werden muss und statstatt der eigentlichen Dateidaten nur die angeforderten Eingabedateien / -ordner von der Festplatte gelesen werden müssen.

Der folgende Code enthält Implementierungen der close, readund writePOSIX - Funktionen. Das Makro OUT_FDsteuert, welcher Dateideskriptor tarals Ausgabedatei verwendet werden soll. Derzeit ist es auf stdout eingestellt.

readwurde so geändert, dass nur der Erfolgswert von countBytes zurückgegeben wird, anstatt buf mit den Daten zu füllen, da die tatsächlichen Daten nicht gelesen wurden. buf würde keine gültigen Daten für die Weitergabe an die Komprimierung enthalten. Wenn also die Komprimierung verwendet würde, würden wir einen falschen Wert berechnen Größe.

writewurde geändert, um die Eingabebytes countin die globale Variable zu summieren totalund den Erfolgswert von countBytes nur dann zurückzugeben, wenn der Dateideskriptor übereinstimmt OUT_FD. Andernfalls wird der ursprüngliche Wrapper dlsymaufgerufen, der über erworben wurde , um den gleichnamigen Syscall auszuführen.

closeDie ursprüngliche Funktionalität bleibt erhalten, aber wenn der Dateideskriptor mit OUT_FD übereinstimmt, tarwird versucht, eine tar-Datei zu schreiben. Die totalZahl ist also endgültig und wird auf stdout gedruckt.

#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-Vergleich einer Lösung, bei der der Lesezugriff auf die Festplatte und alle Systemaufrufe des normalen Tar-Vorgangs mit der LD_PRELOADLösung durchgeführt werden.

$ 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

Der obige Code, ein grundlegendes Erstellungsskript, um das Obige als gemeinsam genutzte Bibliothek zu erstellen, und ein Skript mit der " LD_PRELOADTechnik", die es verwendet, sind im Repository enthalten: https://github.com/G4Vi/tarsize

Einige Informationen zur Verwendung von LD_PRELOAD: https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/

G4Vi
quelle
Code ist gut, wenn er funktioniert, aber können Sie beschreiben, was er tut? Bitte antworten Sie nicht in Kommentaren; Bearbeiten Sie  Ihre Antwort, um sie klarer und vollständiger zu gestalten.
G-Man sagt, dass Monica