Contexte: serveur physique, âgé d'environ deux ans, disques SATA à 7 200 tr / min connectés à une carte RAID 3Ware, ext3 FS monté avec noatime et data = commandé, pas sous une charge folle, noyau 2.6.18-92.1.22.el5, temps de disponibilité 545 jours . Directory ne contient aucun sous-répertoire, mais des millions de petits fichiers (~ 100 octets), avec des fichiers plus volumineux (quelques Ko).
Nous avons un serveur qui est devenu un peu coucou au cours des derniers mois, mais nous ne l’avons remarqué que l’autre jour quand il a commencé à être incapable d’écrire dans un répertoire car il contenait trop de fichiers. Plus précisément, il a commencé à générer cette erreur dans / var / log / messages:
ext3_dx_add_entry: Directory index full!
Le disque en question a beaucoup d’inodes restants:
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 60719104 3465660 57253444 6% /
Donc, je suppose que cela signifie que nous atteignons la limite du nombre d'entrées pouvant être dans le fichier répertoire lui-même. Aucune idée du nombre de fichiers, mais il ne peut pas y avoir plus de trois millions à peu près, comme vous pouvez le constater. Ce n'est pas bien, remarquez! Mais c’est la première partie de ma question: quelle est exactement cette limite supérieure? Est-ce accordable? Avant que je me crié dessus, je veux le régler vers le bas ; cet énorme répertoire a causé toutes sortes de problèmes.
Quoi qu'il en soit, nous avons repéré le problème dans le code qui générait tous ces fichiers, et nous l'avons corrigé. Maintenant, je suis coincé avec la suppression du répertoire.
Quelques options ici:
rm -rf (dir)
J'ai essayé ceci en premier. J'ai abandonné et je l'ai tué après une journée et demie sans impact perceptible.
- unlink (2) sur le répertoire: Cela mérite certainement d'être pris en compte, mais la question est de savoir s'il serait plus rapide de supprimer les fichiers du répertoire via fsck que de supprimer via unlink (2). C'est-à-dire que, d'une manière ou d'une autre, je dois marquer ces inodes comme inutilisés. Bien entendu, cela suppose que je puisse dire à fsck de ne pas supprimer les entrées dans les fichiers de / lost + found; sinon, je viens de déplacer mon problème. En plus de toutes les autres préoccupations, après avoir lu un peu plus à ce sujet, il s'avère que je devrais probablement appeler des fonctions FS internes, car aucune des variantes unlink (2) que je peux trouver ne me permettrait de supprimer allègrement. un répertoire avec des entrées. Caca.
while [ true ]; do ls -Uf | head -n 10000 | xargs rm -f 2>/dev/null; done )
C'est en fait la version abrégée; le vrai que je suis en train d’exécuter, qui ajoute quelques rapports de progression et un arrêt net lorsque nous sommes à court de fichiers à supprimer, est le suivant:
exportation i = 0; time (while [true]; do ls -Uf | tête -n 3 | grep -qF '.png' || Pause; ls -Uf | tête -n 10000 | xargs rm -f 2> / dev / null; exportation i = $ (($ i + 10000)); echo "$ i ..."; terminé )
Cela semble fonctionner plutôt bien. Au moment où j'écris ces lignes, il a supprimé 260 000 fichiers au cours des trente dernières minutes.
- Comme mentionné ci-dessus, la limite d'entrée par répertoire est-elle réglable?
- Pourquoi a-t-il fallu "vrais 7m9.561s / utilisateur 0m0.001s / sys 0m0.001s" pour supprimer un fichier qui était le premier dans la liste renvoyée par
ls -U
, et il a fallu peut-être dix minutes pour supprimer les 10 000 premières entrées avec le commande en n ° 3, mais maintenant il roule assez bien? D'ailleurs, il en a supprimé 260 000 en une trentaine de minutes, mais il lui faut maintenant quinze minutes supplémentaires pour en supprimer 60 000 de plus. Pourquoi les énormes sautes de vitesse? - Y a-t-il une meilleure façon de faire ce genre de chose? Pas stocker des millions de fichiers dans un répertoire; Je sais que c'est idiot, et cela ne serait pas arrivé sous ma montre. Googler le problème et regarder à travers SF et SO offre beaucoup de variations sur ce
find
qui ne va pas être beaucoup plus rapide que mon approche pour plusieurs raisons évidentes. Mais l'idée de delete-via-fsck a-t-elle des jambes? Ou quelque chose d'autre entièrement? Je suis impatient d'entendre des réflexions originales (ou dans la boîte non connue).
Sortie du script final !:
2970000...
2980000...
2990000...
3000000...
3010000...
real 253m59.331s
user 0m6.061s
sys 5m4.019s
Donc, trois millions de fichiers supprimés en un peu plus de quatre heures.
rm -rfv | pv -l >/dev/null
. pv devrait être disponible dans le référentiel EPEL .