35 votes

Trouver les répertoires avec beaucoup de fichiers dans

Donc un de mes clients a reçu un email de Linode aujourd'hui disant que leur serveur causait l'explosion du service de sauvegarde de Linode. Pourquoi ? Trop de fichiers. J'ai ri et j'ai couru :

# df -ih
Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/xvda        2.5M  2.4M   91K   97% /

Merde. 2,4 millions d'inodes utilisés. Qu'est-ce qui s'est passé ?

J'ai cherché les suspects évidents ( /var/{log,cache} et le répertoire où tous les sites sont hébergés) mais je ne trouve rien de vraiment suspect. Quelque part sur cette bête, je suis certain qu'il y a un répertoire qui contient quelques millions de fichiers.

Pour le contexte, l'un de mes mon Les serveurs occupés utilisent 200k inodes et mon ordinateur de bureau (une vieille installation avec plus de 4TB de stockage utilisé) est seulement un peu plus d'un million. Il y a un problème.

Ma question est donc la suivante : comment trouver où se situe le problème ? Y a-t-il un du pour les inodes ?

28voto

Schof Points 952

Vérifiez /lost+found au cas où il y aurait eu un problème de disque et que beaucoup de déchets auraient été détectés comme des fichiers séparés, peut-être à tort.

Vérifiez iostat pour voir si une application produit toujours des fichiers comme des fous.

find / -xdev -type d -size +100k vous dira s'il y a un répertoire qui utilise plus de 100kB d'espace disque. Il s'agit d'un répertoire qui contient beaucoup de fichiers, ou qui a contenu beaucoup de fichiers dans le passé. Il se peut que vous souhaitiez ajuster le chiffre de la taille.

Je ne pense pas qu'il y ait une combinaison d'options pour GNU du pour qu'il compte 1 par entrée de répertoire. Vous pouvez le faire en produisant la liste des fichiers avec find et faire un peu de comptage en awk. Voici une du pour les inodes. Minimalement testé, n'essaie pas de faire face aux noms de fichiers contenant des nouvelles lignes.

#!/bin/sh
find "$@" -xdev -depth | awk '{
    depth = $0; gsub(/[^\/]/, "", depth); depth = length(depth);
    if (depth < previous_depth) {
       # A non-empty directory: its predecessor was one of its files
       total[depth] += total[previous_depth];
       print total[previous_depth] + 1, $0;
       total[previous_depth] = 0;
    }
    ++total[depth];
    previous_depth = depth;
}
END { print total[0], "total"; }'

Utilisation : du-inodes / . Imprime une liste de répertoires non vides avec le nombre total d'entrées qu'ils contiennent et leurs sous-répertoires de manière récursive. Redirigez la sortie vers un fichier et examinez-la à votre guise. sort -k1nr <root.du-inodes | head vous diront les plus grands délinquants.

15voto

Radu Rădeanu Points 156862

Vous pouvez vérifier avec ce script :

#!/bin/bash

if [ $# -ne 1 ];then
  echo "Usage: `basename $0` DIRECTORY"
  exit 1
fi

echo "Wait a moment if you want a good top of the bushy folders..."

find "$@" -type d -print0 2>/dev/null | while IFS= read -r -d '' file; do 
    echo -e `ls -A "$file" 2>/dev/null | wc -l` "files in:\t $file"
done | sort -nr | head | awk '{print NR".", "\t", $0}'

exit 0

Ceci imprime les 10 premiers sous-répertoires par nombre de fichiers. Si vous voulez un top x, changez head avec head -n x , donde x est un nombre naturel plus grand que 0.

Pour des résultats sûrs à 100%, exécutez ce script avec les privilèges de root :

top-bushy-folders

4voto

chad Points 41

Souvent plus rapide que la recherche, si votre base de données de localisation est à jour :

# locate '' | sed 's|/[^/]*$|/|g' | sort | uniq -c | sort -n | tee filesperdirectory.txt | tail

Cela vide toute la base de données locate, enlève tout ce qui dépasse le dernier '/' dans le chemin, puis le tri et "uniq -c" vous donnent le nombre de fichiers/répertoires par répertoire. "sort -n" envoyé à tail pour obtenir les dix répertoires contenant le plus de choses.

4voto

Sebastian Piech Points 41

Un fil un peu ancien mais intéressant, je propose donc mes solutions.

Il utilise d'abord quelques commandes pipées et trouve des répertoires contenant plus de 1000 fichiers :

find / -type d  |awk '{print "echo -n "$0" ---- ; ls -1 "$0" |wc -l "}'|bash |awk -F "----" '{if ($2>1000) print $1}'

La deuxième est simple. Il essaie juste de trouver les répertoires qui ont une taille supérieure à 4096B. Normalement un répertoire vide a 4096B sur le système de fichiers ext4 i 6B sur le xfs :

find / -type d -size +4096c

Vous pouvez bien sûr l'ajuster mais je pense que cela devrait fonctionner dans la plupart des cas avec une telle valeur.

1voto

Gleb Points 1646

Une autre suggestion :

http://www.iasptk.com/20314-ubuntu-find-large-files-fast-from-command-line

Utilisez ces recherches pour trouver les fichiers les plus volumineux sur votre serveur.

Recherche de fichiers de plus de 1 Go

sudo find / -type f -size +1000000k -exec ls -lh {} \ ;

Trouver des fichiers de plus de 100 Mo

sudo find / -type f -size +100000k -exec ls -lh {} \ ;

Recherche de fichiers de plus de 10 Mo

sudo find / -type f -size +10000k -exec ls -lh {} \ ;

La première partie est la commande find qui utilise l'indicateur "-size" pour trouver des fichiers de différentes tailles mesurées en kilo-octets.

La dernière partie à la fin commençant par "-exec" permet de spécifier une commande que l'on veut exécuter sur chaque fichier trouvé. Ici la commande "ls -lh" pour inclure toutes les informations vues lors de l'énumération du contenu d'un répertoire. Le h vers la fin est particulièrement utile car il imprime la taille de chaque fichier dans un format lisible par l'homme.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X