Supprimer des millions de fichiers

38

Je me suis fait remplir des millions d'images GIF. Trop nombreux pour la commande rm.

J'ai essayé la commande de recherche comme ceci:

find . -name "*.gif" -print0 | xargs -0 rm

Le problème, c’est que ma machine est complètement endommagée et entraîne des délais d’expiration pour les clients car c’est un serveur.

Existe-t-il un moyen plus rapide de supprimer tous ces fichiers ... sans verrouiller la machine?

Corepuncher
la source
Je suis à un taux de suppression d'environ 6 Go / h à l'aide de la commande "nice find" ci-dessous. Il faudra probablement 48 heures de suite pour supprimer tous les fichiers. La raison en est que le script de nettoyage a échoué. J'ai dépassé la "horizon des événements" avec la commande rm, puis il s'est enfui.
3
La suppression de la totalité du répertoire ne serait-elle pas sensiblement plus rapide? Il suffit de sortir les "bons" fichiers avant de détruire les fichiers restants ...
tucuxi
Eh bien, chaque fichier est mauvais en ce moment, car il a été déplacé vers / dir_old, et j'ai refait le / dir. Mais rmdir ne rencontrera-t-il pas la même limitation que rm *?
@Corepuncher: Je m'attendrais à ce que la suppression de tout le répertoire (car avec rm -rfserait plus rapide. Ça vaut le coup d'essayer.
Jason R
Je cours actuellement "rm -rf" sur le répertoire. Il fonctionne depuis plus de 20 minutes maintenant ... aucun changement dans la taille du disque. Mais il n’a pas non plus renvoyé automatiquement la "liste d’arguments trop longue". Le seul problème, c’est que ma machine est vraiment martelée et que d’autres choses ralentissent / échouent. Je ne sais pas combien de temps le laisser aller.

Réponses:

44

Plus vite n'est pas nécessairement ce que vous voulez. Vous souhaiterez peut-être exécuter plus lentement , de sorte que la suppression engendre moins de ressources pendant son exécution.

Utilisez gentil (1) pour réduire la priorité d’une commande.

nice find . -name "*.gif" -delete

Pour les processus liés aux E / S, nice (1) pourrait ne pas être suffisant. Le planificateur Linux prend en compte les E / S, pas seulement le processeur, mais vous souhaitez peut-être un contrôle plus précis de la priorité des E / S.

ionice -c 2 -n 7 find . -name "*.gif" -delete

Si cela ne le fait pas, vous pouvez également ajouter un sommeil pour vraiment le ralentir.

find . -name "*.gif" -exec sleep 0.01 \; -delete
John Kugelman soutient Monica
la source
3
wow ... des millions de fichiers avec un sommeil de .1 s ... a besoin d'une journée pour 864000 fichiers.
Glglgl
7
@glglgl Très bien, beau cul. J'ai changé le délai d'attente. :-P
John Kugelman soutient Monica
28
Le sommeil peut être un bon choix, mais agréable ne le fera pas, car la tâche ici est liée IO, pas liée au processeur; vous pouvez essayer ionice à la place. Notez que si le sommeil est trop petit, il sera inutile.
Matteo Italia
3
@glglgl: le fait est que si vous ne voulez pas perturber le service sur le serveur, vous devez y aller lentement, l'heure à laquelle le code se met en veille est là pour permettre au serveur de fonctionner réellement avec le disque.
Matteo Italia
1
+1 pour l' sleepajout - J'avais des problèmes d'étouffement des serveurs sur l'IO malgré l'utilisation ionice -c 3. Cela ajoute de manière significative au temps nécessaire pour effacer les fichiers (bien sûr), mais je préfère attendre que de déposer la demande ...
Ola Tuvesson
22

Puisque vous utilisez Linux et que cette tâche est probablement liée aux E / S, je vous conseille de donner à votre commande la priorité du planificateur d'E / S en mode veille à l'aide de ionice(1):

ionice -c3 find . -name '*.gif' -delete

En comparant avec votre commande d'origine, je suppose que cela pourrait même vous épargner encore plus de cycles de processeur en évitant le tube xargs.


la source
@Braiam Que voulez-vous dire? Ce n'est pas un find ... -execcas où cela aurait du sens.
Oh oui, désolé. Ma faute. Vous êtes sûr que c'est efficace, tho?
Braiam
1
Eh bien, la find(1)documentation le prétend. :) Et il devrait être évident que se laisser findsupprimer lui-même est plus efficace que de forger une rmcommande pour cela.
1
J'ai essayé plusieurs versions suggérées sur un dossier contenant 4 millions de fichiers sur un serveur de production et celui-ci est le seul à ne pas étrangler le système. ionice -c3réduit le prio pour qu'il ne soit exécuté que lorsque l'IO est inactif, sinon c'est parfait. Notez que, comme il -deleten’est pas standard pour la recherche, vous pouvez faire de même (y compris le retour d’information que cela fonctionne) à l’aide de cette commande: ionice -c 3 find . -name '*.gif' -exec echo {} \; -exec rm {} \;- Lent mais pas de processus importants.
Christopher Lörken
13

Non.

Il n'y a pas de moyen plus rapide, mis à part le formatage souple du disque. Les fichiers sont donnés à rm à la fois (jusqu’à la limite de la ligne de commande, il peut également être réglé à laxargs ), ce qui est bien mieux que d'appeler rm sur chaque fichier. Donc non, il n'y a certainement pas de moyen plus rapide.

En utilisant nice (ou renicesur un processus en cours d'exécution) n'aide que partiellement, car c'est pour planifier la ressource CPU , pas le disque! Et l'utilisation du processeur sera très faible. C’est une faiblesse de Linux - si un processus «mange» le disque (c’est-à-dire qu’il travaille beaucoup avec lui), toute la machine reste bloquée. Le noyau modifié pour une utilisation en temps réel pourrait être une solution.

Ce que je ferais sur le serveur est de laisser manuellement les autres processus faire leur travail - inclure des pauses pour garder le serveur "respirer":

find . -name "*.gif" > files
split -l 100 files files.
for F in files.* do
    cat $F | xargs rm
    sleep 5 
done

Cela attend 5 secondes tous les 100 fichiers. Cela prendra beaucoup plus de temps, mais vos clients ne devraient pas remarquer de retard.

Tomas
la source
« Les fichiers sont donnés rm à la fois (jusqu'à la limite de la ligne de commande » -SO lorsque la coque est ordonnée à rm *, il se dilate *dans la ligne avec tous les noms de fichiers et le transmettre à rm? C'est incroyablement stupide. Pourquoi serait shell Développer les wildcards?
:-D @Joker_vD, tu plaisantes, comme ton nom l'indique? :-)
Tomas
2
@Joker_vD: Compatibilité avec une décision Unix à partir de 1970 environ. Windows ne le fait pas. Là, les programmes peuvent transmettre des caractères génériques à FindNextFile / FindNextFile afin d’obtenir les résultats un par un.
MSalters
@Tomas Pas dans ce cas. Honnêtement, je vois immédiatement deux problèmes avec une telle conception: premièrement, la ligne de commande n’est pas en caoutchouc; deuxièmement, le programme ne peut pas dire s'il a été appelé avec *ou /*et donner un doute à une telle décision de l'utilisateur.
1
@Joker_vD Il y a beaucoup de bonnes choses à propos du shell qui développe des caractères génériques. C'est différent de Windows, mais ne concluez pas que c'est incroyablement stupide simplement parce que c'est différent de ce à quoi vous êtes habitué. Si vous souhaitez en savoir plus, je vous encourage à le rechercher sur Google ou à poser une question sur le site Stack Exchange correspondant. C'est un énorme déraillement pour cette zone de commentaire.
John Kugelman soutient Monica
5

Si le nombre de fichiers à supprimer dépasse largement le nombre de fichiers laissés, ce n'est peut-être pas la méthode la plus efficace pour parcourir l'arborescence des fichiers à supprimer et effectuer toutes les mises à jour du système de fichiers. (Cela revient à faire une gestion maladroite de la mémoire comptée en références, visiter chaque objet dans un grand arbre pour laisser tomber sa référence, au lieu de tout mettre en ordre en une seule étape, puis balayer tout ce qui est accessible à nettoyer.)

C’est-à-dire cloner les parties de l’arbre à conserver sur un autre volume. Recréez un nouveau système de fichiers vierge sur le volume d'origine. Copiez les fichiers conservés dans leur chemin d'origine. Ceci est vaguement similaire à la copie d'une récupération de place .

Il y aura des temps morts, mais cela pourrait être mieux que de mauvaises performances continues et des interruptions de service.

Cela peut ne pas être pratique dans votre système et votre situation, mais il est facile d'imaginer des cas évidents où c'est la voie à suivre.

Par exemple, supposons que vous vouliez supprimer tous les fichiers d'un système de fichiers. Quel serait le but de récursir et de supprimer un par un? Démontez-le et faites un "mkfs" sur la partition pour créer un système de fichiers vide.

Ou supposez que vous vouliez supprimer tous les fichiers sauf une demi-douzaine de fichiers importants? Sortez la demi-douzaine et ... "mkfs" par dessus.

Finalement, il y a un seuil de rentabilité quand il y a suffisamment de fichiers qui doivent rester, qu'il devient moins coûteux de faire la suppression récursive, en tenant compte des autres coûts, comme tout temps d'arrêt.

Kaz
la source
4

As-tu essayé:

find . -name "*.gif" -exec rm {} +

Le signe + à la fin fera en sorte que find inclue plus de fichiers pour que la commande unique rm soit exécutée. Cochez cette question pour plus de détails.

Bartosz Firyn
la source
Il s'exécute beaucoup plus vite que -print0 | xargs solution car le processus rm n’est pas appelé pour chaque fichier, mais pour un grand nombre d’entre eux, ce qui entraîne une charge inférieure.
@JohnKugelman Vous avez raison, mais c'est une extension GNU qui n'est pas toujours disponible avec la commande native find .
CodeGnome
OK, intéressant, mais c'est une chose assez nouvelle (ainsi que -delete) qui ne doit pas toujours être là.
Tomas
Cependant, cela n'apporte certainement rien de mieux par rapport à la solution du PO.
Tomas