Temukan direktori dengan banyak file di

33

Jadi seorang klien saya mendapat email dari Linode hari ini mengatakan server mereka menyebabkan layanan cadangan Linode meledak. Mengapa? Terlalu banyak file. Saya tertawa dan kemudian berlari:

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

Sampah. 2,4 juta inode digunakan. Apa yang terjadi ?!

Saya telah mencari tersangka yang jelas ( /var/{log,cache}dan direktori tempat semua situs di-host) tetapi saya tidak menemukan sesuatu yang benar-benar mencurigakan. Di suatu tempat di binatang ini saya yakin ada direktori yang berisi beberapa juta file.

Untuk konteks pertama, server saya yang sibuk menggunakan inode 200k dan desktop saya (instalasi lama dengan lebih dari 4TB penyimpanan yang digunakan) hanya lebih dari satu juta. Ada masalah.

Jadi pertanyaan saya adalah, bagaimana saya menemukan di mana masalahnya? Apakah ada duinode?

Oli
sumber
1
jalankan vmstat -1 100 dan tunjukkan pada kami beberapa dari itu. Waspadalah terhadap jumlah besar di CS (Pergantian konteks). Terkadang sistem file yang gagal dapat kehilangan banyak inode menjadi kesalahan. Atau mungkin secara sah, ada banyak file. Tautan ini akan memberi tahu Anda tentang file dan inode. stackoverflow.com/questions/653096/howto-free-inode-usage Anda mungkin perlu melihat apa yang sedang berjalan / terbuka dengan perintah lsof.
j0h

Jawaban:

23

Periksa /lost+foundkalau-kalau ada masalah disk dan banyak sampah akhirnya terdeteksi sebagai file terpisah, mungkin salah.

Periksa iostatuntuk melihat apakah beberapa aplikasi masih menghasilkan file seperti orang gila.

find / -xdev -type d -size +100kakan memberi tahu Anda jika ada direktori yang menggunakan lebih dari 100kB ruang disk. Itu akan menjadi direktori yang berisi banyak file, atau berisi banyak file di masa lalu. Anda mungkin ingin menyesuaikan angka ukuran.

Saya tidak berpikir ada kombinasi opsi untuk GNU duuntuk membuatnya menghitung 1 per entri direktori. Anda dapat melakukan ini dengan membuat daftar file dengan finddan melakukan sedikit penghitungan dalam awk. Ini adalah duuntuk inode. Diuji minimal, tidak mencoba mengatasi nama file yang berisi baris baru.

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

Penggunaan: du-inodes /. Mencetak daftar direktori yang tidak kosong dengan jumlah total entri di dalamnya dan subdirektori secara rekursif. Arahkan output ke file dan tinjau sesuka Anda. sort -k1nr <root.du-inodes | headakan memberi tahu Anda pelanggar terbesar.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Skripnya memberikan kesalahan: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 Ah, saya mengerti, saya menggunakan kekhasan yang tidak berfungsi pada versi lain. Saya telah menambahkan garis miring terbalik yang menurut saya perlu sesuai POSIX.
Gilles 'SO- berhenti bersikap jahat'
14

Anda dapat memeriksa dengan skrip ini:

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

Ini mencetak 10 subdirektori teratas berdasarkan jumlah file. Jika Anda ingin x atas, ubah headdengan head -n x, di mana xbilangan alami lebih besar dari 0.

Untuk 100% hasil pasti, jalankan skrip ini dengan hak akses root:

folder paling lebat

Radu Rădeanu
sumber
2019: mengangkat 10: read: Illegal option -d... menggosok -dbendera dari readberharap tidak ada hal buruk yang akan terjadi. Akan membiarkan Anda tahu kapan selesai menjalankan ...
Williams
3

Seringkali lebih cepat daripada menemukan, jika basis data lokasi Anda mutakhir:

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

Ini akan membuang seluruh basis data lokasi, menghapus semua yang melewati tanda '/' terakhir di path, lalu sortir dan "uniq -c" memberi Anda jumlah file / direktori per direktori. "sort -n" disalurkan untuk memberi Anda sepuluh direktori dengan banyak hal di dalamnya.

chad
sumber
+1: menggunakan database cari adalah ide yang sangat bagus!
Max Beikirch
Ketika Anda tidak dapat menggunakan mencari untuk alasan apa pun, jalankan yang find /path/to/parent -xdev > filelistpertama, lalu arahkan untuk membaca input dari daftar itu.
gerrit
1

Saran lain:

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

Gunakan pencarian ini untuk menemukan file terbesar di server Anda.

Temukan file lebih dari 1GB

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

Temukan file lebih dari 100MB

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

Temukan file lebih dari 10MB

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

Bagian pertama adalah perintah find menggunakan flag "-size" untuk menemukan file dengan ukuran berbeda yang diukur dalam kilobyte.

Bit terakhir di akhir dimulai dengan "-exec" memungkinkan untuk menentukan perintah yang ingin kita jalankan pada setiap file yang kita temukan. Di sini perintah "ls -lh" untuk memasukkan semua informasi yang dilihat saat mendaftar isi direktori. Jam menjelang akhir sangat membantu karena mencetak ukuran setiap file dalam format yang dapat dibaca manusia.

ptheo
sumber
2
Masalahnya adalah penggunaan inode yang tinggi, yang menunjuk ke banyak file yang lebih kecil, bukan yang besar.
UpTheCreek
0

Ini bekerja untuk saya ketika yang lain gagal di Android melalui shell:

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

Saya suka menggunakan sesuatu seperti du --inodes -d 1untuk menemukan direktori yang baik secara rekursif atau langsung berisi banyak file.

Saya juga menyukai jawaban ini: https://unix.stackexchange.com/a/123052

Bagi kita yang malas, inilah intinya:

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