Określ lokalizację użycia i-węzła


15

Niedawno zainstalowałem Munin na rozwojowym serwerze internetowym, aby śledzić użycie systemu. Zauważyłem, że użycie i-węzła systemu rośnie o około 7-8% dziennie, chociaż użycie dysku prawie wcale nie wzrosło. Zgaduję, że coś pisze mnóstwo małych plików, ale nie mogę znaleźć co / gdzie.

Wiem, jak znaleźć użycie miejsca na dysku, ale nie mogę znaleźć sposobu na podsumowanie użycia i-węzła.

Czy istnieje dobry sposób, aby określić użycie i-węzła według katalogu, dzięki czemu mogę zlokalizować źródło użycia?

Odpowiedzi:


15

Nie oczekuj, że to zadziała szybko ...

cd do katalogu, w którym podejrzewasz, że może istnieć podkatalog z dużą ilością i-węzłów. Jeśli ten skrypt zajmuje dużo czasu, prawdopodobnie znalazłeś, gdzie w systemie plików szukać. / var to dobry początek ...

W przeciwnym razie, jeśli przejdziesz do najwyższego katalogu w tym systemie plików i uruchomisz go i zaczekasz na zakończenie, znajdziesz katalog ze wszystkimi i-węzłami.

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

Nie martwię się o koszty sortowania. Przeprowadziłem test i posortowanie tego nieposortowanego wyjścia w stosunku do 350 000 katalogów zajęło 8 sekund. Pierwsze znalezisko zajęło. Rzeczywistym kosztem jest otwarcie wszystkich tych katalogów w pętli while. (sama pętla zajmuje 22 sekundy). (Dane testowe zostały uruchomione w podkatalogu z 350 000 katalogów, z których jeden miał milion plików, reszta zawierała od 1 do 15 katalogów).

Różni ludzie zauważyli, że ls nie jest w tym świetny, ponieważ sortuje dane wyjściowe. Próbowałem echa, ale to też nie jest świetne. Ktoś inny zauważył, że stat podaje te informacje (liczbę pozycji katalogu), ale nie jest przenośny. Okazuje się, że find -maxdepth jest naprawdę szybki w otwieraniu katalogów i zlicza pliki., Więc ... tutaj są ... punkty dla wszystkich!


2
@ Mike G: Masz 100% rację, że nie jest to najszybszy sposób na zrobienie czegoś takiego. Moim zdaniem poprawnym sposobem na zoptymalizowanie tego jest przekierowanie do stderr podczas uruchamiania i kończenia części skryptu zliczania wpisów do katalogu. W ten sposób, gdy trafisz do katalogu z milionem wpisów, powiesz „Przetwarzanie buforu katalogu / postfix / maildrop”, a następnie nie powie natychmiast „zakończono” i boom - spójrz na szpulę / postfix / maildrop i zobaczysz wiele akta.
Chris

Nie martwiłem się również kosztami sortowania, ponieważ jest to zadanie jednorazowe lub przynajmniej dość rzadkie.
Dave Forgac

7

Jeśli problemem jest jeden katalog ze zbyt dużą liczbą plików, oto proste rozwiązanie:

# Let's find which partition is out of inodes:
$ df -hi
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/sda3               2.4M    2.4M       0  100% /
...

# Okay, now we know the mount point with no free inodes,
# let's find a directory with too many files:
$ find / -xdev -size +100k -type d

Ideą tego findwiersza jest to, że rozmiar katalogu jest proporcjonalny do ilości plików bezpośrednio w tym katalogu. Więc szukamy katalogów z mnóstwem plików w środku.

Jeśli nie chcesz zgadywać numeru i wolisz wymienić wszystkie podejrzane katalogi uporządkowane według „rozmiaru”, to też jest łatwe:

# Remove the "sort" command if you want incremental output
find / -xdev -size +10k -type d -printf '%s %p\n' | sort -n

6

Grrr, komentarz wymaga 50 powtórzeń. Ta odpowiedź jest więc komentarzem do odpowiedzi Chris'a.

Ponieważ pytający prawdopodobnie nie przejmuje się wszystkimi katalogami, tylko najgorszymi, użycie sortowania jest prawdopodobnie bardzo kosztowną przesadą.

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

Nie jest to tak kompletne jak twoja wersja, ale to robi linie wydruku, jeśli są większe niż poprzednie maksimum, znacznie zmniejszając ilość wydrukowanego szumu i oszczędzając koszty tego rodzaju.

Wadą tego jest to, że jeśli masz 2 bardzo duże katalogi, a pierwszy ma o 1 więcej i-węzłów niż drugi, nigdy nie zobaczysz drugiego.

Bardziej kompletnym rozwiązaniem byłoby napisanie mądrzejszego skryptu perlowego, który śledzi 10 najważniejszych wartości i wypisuje je na końcu. Ale to zbyt długo, aby szybko odpowiedzieć na błąd serwera.

Ponadto, nieco bardziej inteligentne skrypty perla pozwoliłyby pominąć pętlę while - na większości platform ls sortuje wyniki, a to może być bardzo kosztowne w przypadku dużych katalogów. Sortowanie ls nie jest tutaj konieczne, ponieważ liczy się tylko liczba.


1
To prawda o ls - w takich sytuacjach martwię się bardziej o to, aby wyjaśnić, co robię, a nie o wydajność. Jestem prawie pewien, że możesz użyć echa $ line / * | wc -w zamiast wiersza ls $ | wc -l i unikniesz problemu sortowania ls.
Chris

Właśnie uruchomiłem test na katalogu z milionem plików i ls zajęło 22 sekundy, a echo * zajęło 12 sekund. (Dla przypomnienia, echo * w powłoce nie osiągnie limitu arg, ponieważ echo w 99% aktywnych powłok jest wbudowane)
Chris

ls -f nie posortuje wyników. Sortowanie wyników katalogów prowadzi do typowego problemu z NFS i dużymi katalogami. Jeśli czas czytania i sortowania katalogu (na serwerze) przekroczy limit czasu NFS, katalog i podkatalogi nie będą nadawać się do użytku.
mpez0

5

Możesz użyć tego małego fragmentu:

find | cut -d/ -f2 | uniq -c | sort -n

Wydrukuje, ile plików i katalogów znajduje się w każdym z katalogów w bieżącym folderze, z największymi przestępcami na dole. Pomoże Ci znaleźć katalogi zawierające wiele plików. ( więcej informacji )


To działało doskonale.
ptman

3

To nie jest bezpośrednia odpowiedź na twoje pytanie, ale wyszukiwanie ostatnio zmodyfikowanych plików o małym rozmiarze za pomocą find może zawęzić wyszukiwanie:

find / -mmin -10 -size -20k

3
find /path ! -type d | sed 's,/[^/]*$,,' | uniq -c | sort -rn

ls nie znajdzie pliki, których nazwy zaczynają się od kropki. Używanie find pozwala tego uniknąć. Znajduje każdy plik w drzewie katalogów, odcina nazwę basename od końca każdej ścieżki i zlicza ile razy każda ścieżka katalogu pojawia się w wynikowym wyniku. Może być konieczne wstawienie „!” w cytatach, jeśli twoja skorupa na to narzeka.

I-węzły mogą być również wykorzystywane przez pliki, które zostały usunięte, ale są utrzymywane otwarte przez uruchomiony proces. Jeśli ten pakiet Munin zawiera jakieś stale działające programy, inną rzeczą do sprawdzenia jest to, czy przechowuje on nietypową liczbę plików.


I-węzły mogą być również pobierane przez naprawdę głębokie katalogi, których nie znajdzie. Jest w tym wiele dziwnych przypadków brzegowych, ale najczęstszą sytuacją jest katalog pełen plików o normalnych nazwach.
Chris

3

Brute force to jeden: uruchom tripwire na całym urządzeniu, aby uzyskać linię bazową, a następnie uruchom test jakiś czas później, a katalog przestępców wystanie jak obolały kciuk.


To zajmie prawdopodobnie miliard lat. Szybsze jest uruchomienie lsof | grep DIR i poszukaj w każdym z tych katalogów wielu nowych plików.
Chris

2
Ok, a co z tym: znajdź / | sort> /tmp/find1.txt; znajdź / | sort> /tmp/find2.txt; diff /tmp/find1.txt /tmp/find2.txt
Geoff Fritz

2

(brak możliwości komentowania naprawdę się starzeje - dotyczy to egorgry)

egorgry - ls -i drukuje i-węzeł NUMBER dla pozycji, a nie i-COUNT.

Wypróbuj go z plikiem w katalogu - prawdopodobnie zobaczysz równie wysoką liczbę, ale to nie jest liczba i-węzłów, to tylko i-węzeł #, na który wskazuje twój wpis w katalogu.


lol. Głosowałem za tobą. Dziękuję za wyjaśnienie. użycie i-węzła zawsze było mylące.
egorgry,

dzięki Teraz boję się przekształcić to w komentarz na twoim węźle, na wypadek, gdy stracę karmę po usunięciu tej odpowiedzi :)
Mike G.

2

Aktualizacja

Jeden linijka, która zwraca liczbę i-węzłów każdego potomka danego katalogu z największymi wpisami na dole.

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

Oryginalna odpowiedź

#!/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

Uruchom go w ten sposób (biorąc pod uwagę, że powyższy skrypt znajduje się w pliku wykonywalnym w katalogu roboczym)

./indist / | sort -n

1

użycie i-węzła wynosi około jednego na plik lub katalog, prawda? Tak też

find [path] -print | wc -l

policzyć w przybliżeniu, ile i-węzłów jest używanych w [ścieżka].


1

Próbowałem napisać skuteczny potok powłoki, ale stał się nieporęczny i albo powolny, albo niedokładny, np.

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

wyświetli katalogi liści (i niektóre inne) zawierające ponad 1000 plików. Oto skrypt Perla, który wykonuje to skutecznie zarówno pod względem czasu, jak i pamięci RAM. Wyjście jest jak

«Pliki w poddrzewie» «pliki bezpośrednio w katalogu» «nazwa katalogu»

dzięki czemu można go łatwo masować i filtrować za pomocą zwykłych narzędzi, np. sortuj (1) lub awk (1) jak wyżej.

#! /usr/bin/perl -w
# Written by Kjetil Torgrim Homme <kjetil.homme@redpill-linpro.com>

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
[gregm@zorak2 /]$ ls -i /home
131191 gregm

mój dom na moim laptopie używa i-węzłów 131191.


3
ls -i drukuje i-węzeł NUMBER dla pozycji, a nie i-COUNT. Wypróbuj go z plikiem w katalogu - prawdopodobnie zobaczysz równie wysoką liczbę, ale to nie jest liczba i-węzłów, to tylko i-węzeł #, na który wskazuje twój wpis w katalogu.
egorgry,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.