Comment puis-je déterminer si l'exécution de tar entraînera le remplissage du disque

22

Si je cours tar -cvfsur un répertoire de taille 937 Mo pour créer une copie facilement téléchargeable d'une structure de dossiers profondément imbriquée, est-ce que je risque de remplir le disque étant donné la df -hsortie suivante :

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

Questions connexes:

  • Si le disque peut se remplir, pourquoi donc qu'est-ce que Linux (Amazon AMI) et / ou tarferont sous le capot?
  • Comment puis-je déterminer précisément ces informations moi-même sans demander à nouveau?
codecowboy
la source
Je ne sais pas si c'est possible sans traiter l'archive, mais vous pouvez jouer avec l' --totalsoption. Quoi qu'il en soit, si vous remplissez le disque, vous pouvez simplement supprimer l'archive, à mon humble avis. Pour vérifier toutes les options disponibles, vous pouvez passer par tar --help.
UVV
4
Tangentiellement: ne créez pas le fichier tar en tant que root, un certain pourcentage d'espace sur le disque est réservé à root exclusivement, exactement pour le type de "J'ai rempli le disque et maintenant je ne peux plus me connecter car cela écrirait. bash_history ou autre "situation.
Ulrich Schwarz

Réponses:

24

tar -c data_dir | wc -c sans compression

ou

tar -cz data_dir | wc -c avec compression gzip

ou

tar -cj data_dir | wc -c avec compression bzip2

affichera la taille de l'archive qui serait créée en octets, sans écrire sur le disque. Vous pouvez ensuite comparer cela à la quantité d'espace libre sur votre appareil cible.

Vous pouvez vérifier la taille du répertoire de données lui-même, au cas où une supposition incorrecte aurait été faite concernant sa taille, avec la commande suivante:

du -h --max-depth=1 data_dir

Comme déjà répondu, tar ajoute un en-tête à chaque enregistrement de l'archive et arrondit également la taille de chaque enregistrement à un multiple de 512 octets (par défaut). La fin d'une archive est marquée par au moins deux enregistrements consécutifs remplis de zéro. Il est donc toujours vrai que vous aurez un fichier tar non compressé plus grand que les fichiers eux-mêmes, le nombre de fichiers et leur alignement sur les limites de 512 octets déterminent l'espace supplémentaire utilisé.

Bien sûr, les systèmes de fichiers eux-mêmes utilisent des tailles de bloc qui peuvent être plus grandes que le contenu d'un fichier individuel, alors faites attention où vous le décompressez, le système de fichiers peut ne pas être capable de contenir beaucoup de petits fichiers même s'il a un espace libre supérieur à la taille tar!

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

FantasticJamieBurns
la source
Merci Jamie! Que fait '- mysql' ici? C'est votre nom de fichier?
codecowboy
Je viens de changer ça ... c'est le chemin vers votre répertoire de données.
FantasticJamieBurns
1
Ce n'est pas vraiment important, mais l'utilisation de la combinaison d'arguments -f -pour tar est redondante, car vous pouvez simplement ignorer l' -fargument pour écrire le résultat dans stdout (ie tar -c data_dir).
6

La taille de votre fichier tar sera de 937 Mo plus la taille des métadonnées nécessaires pour chaque fichier ou répertoire (512 octets par objet), et un remplissage ajouté pour aligner les fichiers sur une limite de 512 octets.

Un calcul très approximatif nous indique qu'une autre copie de vos données vous laissera 3,4 Go de libre. Dans 3,4 Go, nous avons de la place pour environ 7 millions d'enregistrements de métadonnées, en supposant qu'il n'y ait pas de remplissage, ou moins si vous supposez une moyenne de 256 octets de remplissage par fichier. Donc, si vous avez des millions de fichiers et de répertoires à tarer, vous pourriez rencontrer des problèmes.

Vous pouvez atténuer le problème en

  • compression à la volée en utilisant les options zou jpourtar
  • faire en tartant qu'utilisateur normal afin que l'espace réservé sur la /partition ne soit pas touché si vous manquez d'espace.
Flup
la source
2

tarlui-même peut rendre compte de la taille de ses archives avec l' --testoption:

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

La commande ci-dessus n'écrit rien sur le disque et présente l'avantage supplémentaire de répertorier les tailles de fichier individuelles de chaque fichier contenu dans l'archive tar. Ajouter les différents z/j/xzopérandes de chaque côté du|pipe poignée gérera la compression comme vous le feriez.

PRODUCTION:

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

Pas entièrement sûr de votre objectif, mais s'il s'agit de télécharger l'archive tar, cela pourrait être plus pertinent:

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

Ou simplement copier avec tar:

ssh you@host 'tar -cf - ./* | cat' | tar -C/path/to/download/tree/destination -vxf -
mikeserv
la source
La raison pour laquelle je fais cela est que je pense que le répertoire en question a fait que la sortie de df -i atteint 99%. Je veux conserver une copie du répertoire pour une analyse plus approfondie, mais je veux effacer l'espace
codecowboy
@codecowboy Dans ce cas, vous devez certainement faire quelque chose comme ci-dessus en premier. Il tarcopiera ensuite l'arborescence sur votre disque local dans un flux sans rien enregistrer sur le disque distant, après quoi vous pourrez le supprimer de l'hôte distant et le restaurer plus tard. Vous devriez probablement ajouter -zpour la compression comme le souligne Goldilocks, pour économiser sur la bande passante à mi-transfert.
mikeserv
@ TAFKA'goldilocks 'Non, car c'est 99% d'inodes, pas 99% d'espace.
Gilles 'SO- arrête d'être méchant'
-ià droite, désolé!
goldilocks
@mikeserv votre ligne d'ouverture mentionne l'option --test mais vous ne semblez pas alors l'utiliser dans votre commande qui suit immédiatement (elle utilise --totals)
codecowboy
2

J'ai fait beaucoup de recherches à ce sujet. Vous pouvez faire un test sur le fichier avec un nombre de mots, mais il ne vous donnera pas le même numéro qu'un du -sb adir.

tar -tvOf afile.tar | wc -c

ducompte chaque répertoire comme 4096 octets et tarcompte les répertoires comme 0 octet. Vous devez ajouter 4096 à chaque répertoire:

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

alors vous devez ajouter tous les personnages. Pour quelque chose qui ressemble à ceci:

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

Je ne sais pas si c'est parfait car je n'ai pas essayé les fichiers qui ont été touchés (fichiers de 0 octet) ou les fichiers qui ont 1 caractère. Cela devrait vous rapprocher.

tass6773
la source
1

-cvfn'inclut aucune compression, ce qui fait que sur un dossier de ~ 1 Go se traduira par un fichier tar de ~ 1 Go (la réponse de Flub contient plus de détails sur la taille supplémentaire dans le fichier tar, mais notez que même s'il y a 10000 fichiers, ce n'est que 5 Mo). Étant donné que vous disposez de 4 Go ou plus, non, vous ne remplirez pas la partition.

une copie facilement téléchargeable

La plupart des gens considéreraient "plus facile" comme "plus petit" en termes de téléchargement, vous devriez donc utiliser une compression ici. bzip2devrait maintenant être disponible sur n'importe quel système avec tar, je pense, donc l'inclusion jdans vos commutateurs est probablement le meilleur choix. z( gzip) est peut-être encore plus courant, et il existe d'autres possibilités (moins omniprésentes) avec plus de squash.

Si vous voulez dire, tarutilise temporairement de l'espace disque supplémentaire pour effectuer la tâche, je suis sûr que ce n'est pas le cas pour plusieurs raisons, l'une étant à une époque où les lecteurs de bande étaient une forme de stockage principal, et deux étant a eu des décennies à évoluer (et je suis certain qu'il n'est pas nécessaire d'utiliser un espace intermédiaire temporaire, même si la compression est impliquée).

boucle d'or
la source
0

Si la vitesse est importante et que la compression n'est pas nécessaire, vous pouvez accrocher les wrappers syscall utilisés à l' taraide de LD_PRELOAD, pour les modifier taret les calculer pour nous. En réimplémentant quelques - unes de ces fonctions pour répondre à nos besoins (calcul de la taille des données de goudron de la production potentielle), nous sommes en mesure d' éliminer beaucoup de readet writequi est effectué en fonctionnement normal tar. Cela rend tarbeaucoup plus rapide car il n'a pas besoin de basculer le contexte d'avant en arrière dans le noyau à peu près autant et seul le statfichier / dossier d'entrée requis doit être lu à partir du disque au lieu des données de fichier réelles.

Le code ci - dessous comprend les mises en œuvre des close, readet des writefonctions POSIX. La macro OUT_FDcontrôle le descripteur de fichier que nous prévoyons tard'utiliser comme fichier de sortie. Actuellement, il est défini sur stdout.

reada été modifié pour renvoyer simplement la valeur de succès des countoctets au lieu de remplir buf avec les données, étant donné que les données réelles n'ont pas été lues buf ne contiendrait pas de données valides pour passer à la compression, et donc si la compression était utilisée, nous calculerions une erreur Taille.

writea été modifié pour additionner les countoctets d' entrée dans la variable globale totalet renvoyer la valeur de succès des countoctets uniquement si le descripteur de fichier correspond OUT_FD, sinon il appelle l'encapsuleur d'origine acquis via dlsympour effectuer l'appel système du même nom.

closepréforme toujours toutes ses fonctionnalités d'origine, mais si le descripteur de fichier correspond à OUT_FD, il sait que cela tarest fait en essayant d'écrire un fichier tar, donc le totalnombre est final et il l'imprime sur 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 comparant une solution où l'accès au disque de lecture et tous les appels système de l'opération tar normale sont effectués par rapport à la LD_PRELOADsolution.

$ 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

Le code ci-dessus, un script de construction de base pour construire ce qui précède en tant que bibliothèque partagée et un script avec la " LD_PRELOADtechnique" l'utilisant sont fournis dans le référentiel: https://github.com/G4Vi/tarsize

Quelques informations sur l'utilisation de LD_PRELOAD: https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/

G4Vi
la source
Le code est bon, s'il fonctionne, mais pouvez-vous décrire ce qu'il fait? Veuillez ne pas répondre dans les commentaires; modifiez  votre réponse pour la rendre plus claire et plus complète.
G-Man dit `` Réintègre Monica '' le