Znajdź katalogi z dużą ilością plików

33

Więc mój klient otrzymał dzisiaj od Linode wiadomość e-mail z informacją, że jego serwer spowodował awarię usługi tworzenia kopii zapasowych Linode. Czemu? Za dużo plików. Zaśmiałem się, a potem pobiegłem:

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

Bzdury. W użyciu jest 2,4 miliona i-węzłów. Co się do cholery dzieje ?!

Szukałem oczywistych podejrzanych ( /var/{log,cache}i katalogu, z którego hostowane są wszystkie strony), ale nie znalazłem niczego naprawdę podejrzanego. Gdzieś na tej bestii jestem pewien, że jest tam katalog zawierający kilka milionów plików.

Dla pierwszego kontekstu moje zajęte serwery używają 200 000 i-węzłów, a mój pulpit (stara instalacja z ponad 4 TB używanego miejsca) to tylko nieco ponad milion. Tam jest problem.

Więc moje pytanie brzmi: jak mogę znaleźć, gdzie jest problem? Czy istnieje dudla i-węzłów?

Oli
źródło
1
uruchom vmstat -1 100 i pokaż nam niektóre z nich. uważaj na dużą liczbę w CS (przełączanie kontekstu). Czasami wadliwy system plików może stracić dużo i-węzłów na błędy. A może zgodnie z prawem istnieje wiele plików. Ten link powinien informować cię o plikach i i-węzłach. stackoverflow.com/questions/653096/howto-free-inode-usage może być konieczne sprawdzenie, co jest uruchomione / otwarte za pomocą polecenia lsof.
j0h

Odpowiedzi:

23

Sprawdź, czy /lost+foundnie wystąpił problem z dyskiem i wiele śmieci zostało wykrytych jako osobne pliki, być może nieprawidłowo.

Sprawdź, iostatczy jakaś aplikacja nadal generuje pliki takie jak szalone.

find / -xdev -type d -size +100kpoinformuje Cię, czy istnieje katalog, który zajmuje więcej niż 100kB miejsca na dysku. Byłby to katalog, który zawiera wiele plików lub zawierał wiele plików w przeszłości. Możesz dostosować wielkość figury.

Nie sądzę, aby GNU zawierało kombinację opcji, aby duliczyć 1 na pozycję katalogu. Możesz to zrobić, tworząc listę plików findi wykonując odrobinę liczenia w awk. Oto i- duwęzły. Minimalnie przetestowany, nie próbuje poradzić sobie z nazwami plików zawierającymi znaki nowej linii.

#!/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"; }'

Zastosowanie: du-inodes /. Drukuje listę niepustych katalogów z całkowitą liczbą wpisów w nich i ich podkatalogów rekurencyjnie. Przekieruj wyjście do pliku i przejrzyj go w dowolnym momencie. sort -k1nr <root.du-inodes | headpowie Ci największych przestępców.

Gilles „SO- przestań być zły”
źródło
Skrypt podaje błędy:awk: line 2: find: regular expression compile failed (bad class -- [], [^] or [) [^ awk: line 2: syntax error at or near ] `/tmp/tmpw99dhs': Permission denied
Radu Rădeanu
@ RaduRădeanu Ach, rozumiem, użyłem osobliwości gawk, która nie działa w innych wersjach. Dodałem ukośnik odwrotny, który moim zdaniem jest konieczny zgodnie z POSIX.
Gilles „SO- przestań być zły”
14

Możesz sprawdzić za pomocą tego skryptu:

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

Spowoduje to wydrukowanie 10 najlepszych podkatalogów według liczby plików. Jeśli chcesz górnego x, zmień za headpomocą head -n x, gdzie xliczba naturalna jest większa niż 0.

Aby uzyskać 100% pewności wyników, uruchom ten skrypt z uprawnieniami administratora:

top-krzaczaste foldery

Radu Rădeanu
źródło
2019: podniesiony 10: read: Illegal option -d... wyszarpał -dflagę, readmając nadzieję, że nic złego się nie stanie. Powiadomi Cię, kiedy zakończy bieganie ...
Williams
3

Często szybciej niż znajdź, jeśli twoja zlokalizowana baza danych jest aktualna:

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

Spowoduje to zrzucenie całej zlokalizowanej bazy danych, usunięcie wszystkiego poza ostatnim „/” na ścieżce, a następnie sortowanie i „uniq -c” dostarczy ci liczbę plików / katalogów na katalog. „sort -n” biegnie do końca, aby uzyskać dziesięć katalogów z największą liczbą elementów.

Czad
źródło
+1: użycie zlokalizowanej bazy danych to bardzo fajny pomysł!
Max Beikirch
Jeśli nie możesz użyć funkcji lokalizacji z jakiegokolwiek powodu, uruchom find /path/to/parent -xdev > filelistnajpierw, a następnie skieruj sed, aby odczytać dane wejściowe z tej listy.
gerrit
1

Kolejna sugestia:

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

Skorzystaj z tych wyszukiwań, aby znaleźć największe pliki na swoim serwerze.

Znajdź pliki powyżej 1 GB

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

Znajdź pliki powyżej 100 MB

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

Znajdź pliki powyżej 10 MB

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

Pierwszą częścią jest polecenie find używające flagi „-size” do znajdowania plików o różnych rozmiarach mierzonych w kilobajtach.

Ostatni bit na końcu, zaczynający się od „-exec”, pozwala określić polecenie, które chcemy wykonać dla każdego znalezionego pliku. Tutaj polecenie „ls -lh”, aby uwzględnić wszystkie informacje wyświetlane podczas wyświetlania zawartości katalogu. Symbol h pod koniec jest szczególnie pomocny, ponieważ drukuje rozmiar każdego pliku w formacie czytelnym dla człowieka.

ptheo
źródło
2
Jego problemem jest wysokie użycie i-węzła, które wskazuje na wiele mniejszych plików, nie dużych.
UpTheCreek
0

To zadziałało dla mnie, gdy druga nie działała na Androidzie przez powłokę:

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

Lubię używać czegoś takiego, jak du --inodes -d 1znaleźć katalog, który albo rekurencyjnie, albo bezpośrednio zawiera wiele plików.

Podoba mi się również ta odpowiedź: https://unix.stackexchange.com/a/123052

Dla leniwych oto sedno tego:

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