Trova le directory con molti file in


33

Quindi un mio cliente ha ricevuto un'email da Linode oggi dicendo che il suo server stava causando l'esplosione del servizio di backup di Linode. Perché? Troppi file. Ho riso e poi ho corso:

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

Una schifezza. 2,4 milioni di inode in uso. Che diavolo sta succedendo ?!

Ho cercato gli ovvi sospetti ( /var/{log,cache}e la directory da cui sono ospitati tutti i siti) ma non trovo nulla di veramente sospetto. Da qualche parte su questa bestia sono certo che c'è una directory che contiene un paio di milioni di file.

Per un contesto miei miei assistenti occupati utilizza 200k inode e il mio desktop (una vecchia installazione con oltre 4 TB di stoccaggio usate) è solo poco più di un milione. C'è un problema.

Quindi la mia domanda è: come trovo dove si trova il problema? C'è un duinode?



1
esegui vmstat -1 100 e mostracene alcuni. attenzione al gran numero in CS (cambio di contesto). A volte un filesystem in errore può perdere molti inode a causa di errori. O forse legittimamente, ci sono molti file. Questo link dovrebbe informarti su file e inode. stackoverflow.com/questions/653096/howto-free-inode-usage potresti aver bisogno di vedere cosa è in esecuzione / aprire con il comando lsof.
j0h

Risposte:


23

Controlla /lost+foundnel caso ci sia stato un problema con il disco e un sacco di spazzatura finisse per essere rilevata come file separati, possibilmente erroneamente.

Controlla iostatse qualche applicazione sta ancora producendo file come un matto.

find / -xdev -type d -size +100kti dirà se esiste una directory che utilizza più di 100 KB di spazio su disco. Sarebbe una directory che contiene molti file o conteneva molti file in passato. Potresti voler regolare la dimensione.

Non penso che ci sia una combinazione di opzioni per GNU duper farla contare 1 per voce della directory. Puoi farlo producendo l'elenco dei file con finde facendo un po 'di conteggio in awk. Ecco un duinode. Testato minimamente, non cerca di far fronte a nomi di file contenenti newline.

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

Uso: du-inodes /. Stampa un elenco di directory non vuote con il conteggio totale delle voci in esse e delle relative sottodirectory ricorsivamente. Reindirizza l'output su un file ed esaminalo a tuo piacimento. sort -k1nr <root.du-inodes | headti dirà i più grandi trasgressori.


La sceneggiatura awk: line 2: find: regular expression compile failed (bad class -- [], [^] or [) [^ awk: line 2: syntax error at or near ] `/tmp/tmpw99dhs': Permission denied
riporta

@ RaduRădeanu Ah, vedo, ho usato una peculiarità gawk che non funziona in altre versioni. Ho aggiunto una barra rovesciata che ritengo necessaria secondo POSIX.
Gilles 'SO- smetti di essere malvagio' il

14

Puoi verificare con questo 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

Questo stampa le prime 10 sottodirectory per numero di file. Se vuoi una x in alto, cambia headcon head -n x, dove xè un numero naturale maggiore di 0.

Per risultati sicuri al 100%, esegui questo script con i privilegi di root:

top-cespugliose-cartelle


2019: sollevato 10: read: Illegal option -d... sfregato la -dbandiera dalla readsperanza che non accada nulla di brutto. Ti farà sapere quando finirà di funzionare ...
Williams,

3

Spesso più veloce di find, se il database di individuazione è aggiornato:

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

In questo modo viene scaricato l'intero database di individuazione, viene rimosso tutto oltre l'ultimo '/' nel percorso, quindi l'ordinamento e "uniq -c" forniscono il numero di file / directory per directory. "sort -n" ha convogliato in coda per farti avere le dieci directory con il maggior numero di cose.


+1: usare il database di individuazione è una buona idea!
Max Beikirch,

Quando non è possibile utilizzare la funzione di individuazione per qualsiasi motivo, eseguire un find /path/to/parent -xdev > filelistprimo, quindi dirigere sed per leggere l'input da tale elenco.
Gerrit,

1

Un altro suggerisce:

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

Usa queste ricerche per trovare i file più grandi sul tuo server.

Trova file oltre 1 GB

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

Trova file di dimensioni superiori a 100 MB

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

Trova file di oltre 10 MB

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

La prima parte è il comando find che utilizza il flag "-size" per trovare file di dimensioni diverse misurate in kilobyte.

L'ultimo bit alla fine che inizia con "-exec" consente di specificare un comando che vogliamo eseguire su ogni file che troviamo. Qui il comando "ls -lh" per includere tutte le informazioni visualizzate quando si elencano i contenuti di una directory. La h verso la fine è particolarmente utile in quanto stampa le dimensioni di ciascun file in un formato leggibile dall'uomo.


2
Il suo problema è l'uso elevato dell'inode, che punta a molti file più piccoli, non a quelli più grandi.
UpTheCreek,

0

Questo ha funzionato per me quando l'altro è fallito su Android attraverso la shell:

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

0

Mi piace usare qualcosa come du --inodes -d 1trovare una directory che contenga ricorsivamente o direttamente molti file.

Mi piace anche questa risposta: https://unix.stackexchange.com/a/123052

Per i più pigri, ecco l'essenza:

du --inodes -S | sort -rh | sed -n \
    '1,50{/^.\{71\}/s/^\(.\{30\}\).*\(.\{37\}\)$/\1...\2/;p}'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.