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?
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 iostat
pour 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 du
afin que le nombre compte 1 par entrée de répertoire. Vous pouvez le faire en générant la liste de fichiers avec find
et en effectuant un peu de comptage dans awk. Voici un du
pour 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.
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:
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.
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.
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}'
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