web-dev-qa-db-fra.com

Trouver des répertoires avec beaucoup de fichiers dans

Un de mes clients a donc reçu un courrier électronique de Linode indiquant que son serveur faisait exploser le service de sauvegarde de Linode. Pourquoi? Trop de fichiers. J'ai ri puis 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 existe un répertoire contenant quelques millions de fichiers.

Pour le contexte un, mes my serveurs occupés utilisent 200 000 inodes et mon ordinateur de bureau (une ancienne installation avec plus de 4 To de stockage utilisé) ne représente qu'un peu plus d'un million. Il ya un problème.

Donc ma question est, comment puis-je trouver où le problème est? Existe-t-il un du pour les inodes?

33
Oli

Vérifiez /lost+found au cas où il y aurait un problème de disque et que beaucoup de fichiers inutiles ont été détectés sous forme de fichiers séparés, éventuellement à tort.

Vérifiez iostatpour voir si une application produit toujours des fichiers aussi fous.

find / -xdev -type d -size +100k vous dira s'il existe un répertoire qui utilise plus de 100 Ko d'espace disque. Ce serait un répertoire qui contient beaucoup de fichiers, ou contenait beaucoup de fichiers dans le passé. Vous voudrez peut-être ajuster la taille.

Je ne pense pas qu'il y ait une combinaison d'options pour GNU duafin que le nombre compte 1 par entrée de répertoire. Vous pouvez le faire en générant la liste de fichiers avec findet en effectuant un peu de comptage dans awk. Voici un dupour les inodes. Minimalement testé, n'essaye pas de gérer les noms de fichiers contenant des sauts de 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. Rediriger la sortie vers un fichier et le réviser à votre guise. sort -k1nr <root.du-inodes | head vous dira les plus gros délinquants.

23
Gilles

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

Cela permet d’imprimer les 10 premiers sous-répertoires par nombre de fichiers. Si vous voulez un x supérieur, changez head avec head -n x, où x est un nombre naturel supérieur à 0.

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

top-bushy-folders

14
Radu Rădeanu

Souvent plus rapide que find, 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 la totalité de la base de données de localisation, supprime tout ce qui se trouve après le dernier '/' du chemin, puis le tri et "uniq -c" vous donnent le nombre de fichiers/répertoires par répertoire. "sort -n" va vous chercher les dix répertoires contenant le plus de choses.

3
chad

Une autre suggère:

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.

Trouver des 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 {} \;

Trouver des fichiers de plus de 10 Mo

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

La première partie est la commande de recherche utilisant l'indicateur "-size" pour rechercher des fichiers de différentes tailles, mesurés en kilo-octets.

Le dernier bit à la fin commençant par "-exec" permet de spécifier une commande que nous voulons exécuter sur chaque fichier trouvé. Ici, la commande "ls -lh" doit inclure toutes les informations apparaissant lors de la liste 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.

1
ptheo

J'aime utiliser quelque chose comme du --inodes -d 1 pour trouver un répertoire qui contient des fichiers de manière récursive ou directe.

J'aime aussi cette réponse: https://unix.stackexchange.com/a/123052

Pour les paresseux, voici l'essentiel:

du --inodes -S | sort -rh | sed -n \
    '1,50{/^.\{71\}/s/^\(.\{30\}\).*\(.\{37\}\)$/\1...\2/;p}'
0
Tommy Bravo

Cela a fonctionné pour moi lorsque l'autre a échoué sur Android via le shell:

find / -type d -exec sh -c "fc=\$(find '{}' -type f | wc -l); echo -e \"\$fc\t{}\"" \; | sort -nr | head -n25
0
Kevin Parker