web-dev-qa-db-fra.com

Déterminer l'emplacement de l'utilisation de l'inode

J'ai récemment installé Munin sur un serveur Web de développement pour suivre l'utilisation du système. J'ai noté que l'utilisation de l'inode du système augmente d'environ 7 à 8% par jour, même si l'utilisation du disque a à peine augmenté du tout. Je suppose que quelque chose écrit une tonne de fichiers minuscules mais je ne trouve pas quoi/où.

Je sais comment trouver l'utilisation de l'espace disque mais je ne peux pas sembler trouver un moyen de résumer l'utilisation de l'inode.

Y a-t-il un bon moyen de déterminer l'utilisation de l'inode par répertoire afin que je puisse localiser la source de l'utilisation?

15
Dave Forgac

Ne vous attendez pas à courir vite ...

cd dans un répertoire où vous pensez qu'il pourrait y avoir un sous-répertoire avec beaucoup de inodes. Si ce script prend une énorme quantité de temps, vous avez probablement trouvé où dans le système de fichiers à regarder./Var est un bon début ...

Dans le cas contraire, si vous passez dans le répertoire supérieur dans le système de fichiers et d'exécuter cela et attendez à la fin, vous trouverez le répertoire avec tous les inodes.

find . -type d | 
while 
  read line  
do 
  echo "$( find "$line" -maxdepth 1 | wc -l) $line"  
done | 
sort -rn | less

Je ne suis pas inquiet au sujet du coût du tri. J'ai couru un test et le tri par la sortie de ce contre unsorted 350.000 répertoires ont pris 8 secondes. La découverte initiale a pris. Le coût réel ouvre tous ces répertoires dans la boucle while. (La boucle elle-même prend 22 secondes). (Les données de test a été réalisé sur un sous-répertoire avec 350.000 répertoires, dont l'un avait un million de fichiers, le reste avait entre 1 et 15 répertoires).

Plusieurs personnes ont souligné que ls est vraiment pas génial parce que ce trie la sortie. Je l'avais essayé écho, mais c'est pas non plus grand. Quelqu'un d'autre a souligné que stat donne cette information (nombre d'entrées de répertoire), mais que ce n'est pas portable. Il se trouve que trouver -maxdepth est vraiment rapide à l'ouverture .files répertoires et compte, donc ... voilà .. des points pour tout le monde!

15
chris

GRRR, commentaire nécessite 50 représentants. Cette réponse est donc en réalité un commentaire sur la réponse de Chris.

Étant donné que le questionneur ne se soucie probablement de tous les répertoires, seuls les pires, que l'utilisation de tri est probablement très coûteuse.

find . -type d | 
while 
  read line  
do 
  echo "$(ls "$line" | wc -l) $line"  
done | 
Perl -a -ne'next unless $F[0]>=$max; print; $max=$F[0]'  | less

Ce n'est pas aussi complet que votre version, mais ce que cela fait est des lignes d'impression si elles sont plus grandes que le maximum précédent, réduisant énormément la quantité de bruit imprimée et sauvegarde les dépenses du tri.

L'inconvénient de ceci est si vous avez 2 répertoires très volumineux, et le premier se trouve avoir 1 plus d'inode que le 2e, vous ne verrez jamais le 2e.

Une solution plus complète serait d'écrire un script Perl plus intelligent qui garde une trace des 10 meilleures valeurs observées et imprime ceux-ci à la fin. Mais c'est trop long pour une réponse rapide Serverfault.

En outre, certains scripts PERL plus intelligents vous permettraient de sauter la boucle tandis que la plupart des plates-formes, LS trie les résultats, ce qui peut également être très coûteux pour les grands répertoires. Le type LS n'est pas nécessaire ici, car tout ce qui nous intéresse, c'est le compte.

6
Mike G.

Ce n'est pas une réponse directe à votre question, mais la recherche de fichiers récemment modifiés avec une petite taille en utilisant la recherche pourrait réduire votre recherche:

find / -mmin -10 -size -20k
3
Kyle Brandt

Je ferrais brute la force Ceci: exécutez TripWire sur l'ensemble du périphérique pour une base de référence, puis exécutez un chèque de temps plus tard et que le répertoire incriminé collera comme un pouce endolori.

3
Geoff Fritz

(Ne pas pouvoir commenter est vraiment vieux - c'est pour égorgry)

eGORGRY - LS -I imprime le numéro d'inode pour une entrée, pas le nombre d'Inode.

Essayez-le avec un fichier dans votre annuaire - vous voyez (probablement) un nombre tout aussi élevé, mais ce n'est pas le nombre d'inodes, ce n'est que l'inode # Vos points d'entrée de répertoire à.

2
Mike G.

Mettre à jour

Une doublure qui renvoie le nombre d'inodes de chaque enfant de répertoire donné avec les plus grandes entrées en bas.

find . -mindepth 1 -printf "%p/%i\n" \
  | awk -F/ '{print $2"/"$NF}' | sort -u \
  | cut -d/ -f1 | uniq -c | sort -n

Réponse originale

#!/bin/bash
# Show inode distribution for given directory

dirs=$(find $1 -mindepth 1 -maxdepth 1 -type d)

for dir in $dirs
do
    inode_count=$(find $dir -printf "%i\n" 2> /dev/null | sort -u | wc -l)
    echo "$inode_count $dir"
done

Exécutez-le comme ceci (étant donné que le script ci-dessus réside dans un fichier exécutable dans votre répertoire de travail)

./indist / | sort -n
2
raphinesse

l'utilisation de l'inode est d'environ un par fichier ou par répertoire, non? Alors faites

find [path] -print | wc -l

compter environ combien d'inodes sont utilisés sous [Chemin].

1
pjz

J'ai essayé d'écrire un pipeline d'obus efficace, mais il est devenu lourd et lent ou inexact, par ex.,

find . -depth -printf '%h\n' | uniq -c | awk '$1>1000'

liste des annuaires de feuilles (et d'autres) avec plus de 1000 fichiers. Donc, voici un script Perl pour le faire efficacement à la fois dans le temps et la RAM. La sortie est comme

"Fichiers-in-Subtree" "Files-Directement-répertoire" "Nom du répertoire"

vous pouvez donc le massage et le filtrer facilement en utilisant des outils normaux, par exemple, trier (1) ou awk (1) comme ci-dessus.

#! /usr/bin/Perl -w
# Written by Kjetil Torgrim Homme <[email protected]>

use strict;
use File::Find;

my %counted;
my %total;

sub count {
    ++$counted{$File::Find::dir};
}

sub exeunt {
    my $dir = $File::Find::dir;

    # Don't report leaf directories with no files
    return unless $counted{$dir}; 

    my $parent = $dir;
    $parent =~ s!/[^/]*$!!;

    $total{$dir} += $counted{$dir};
    $total{$parent} += $total{$dir} if $parent ne $dir;
    printf("%8d %8d %s\n", $total{$dir}, $counted{$dir}, $dir);
    delete $counted{$dir};
    delete $total{$dir};
}

die "Usage: $0 [DIRECTORY...]\n" if (@ARGV && $ARGV[0] =~ /^-/);
Push(@ARGV, ".") unless @ARGV;

finddepth({ wanted => \&count, postprocess => \&exeunt}, @ARGV);
1
user49026