Encontre diretórios com muitos arquivos em


33

Portanto, um cliente meu recebeu um e-mail da Linode hoje dizendo que seu servidor estava causando a explosão do serviço de backup da Linode. Por quê? Muitos arquivos. Eu ri e depois corri:

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

Porcaria. 2,4 milhões de inodes em uso. Que diabos está acontecendo ?!

Procurei os suspeitos óbvios ( /var/{log,cache}e o diretório de onde todos os sites estão hospedados), mas não estou encontrando nada realmente suspeito. Em algum lugar dessa fera, tenho certeza de que há um diretório que contém alguns milhões de arquivos.

Por um contexto meus meus servidores ocupados usa 200k inodes e meu desktop (um velho instalar com mais de 4 TB de armazenamento usados) é apenas pouco mais de um milhão. Há um problema.

Então, minha pergunta é: como faço para encontrar onde está o problema? Existe um dupara inodes?



1
execute vmstat -1 100 e mostre-nos um pouco disso. cuidado com o grande número no CS (troca de contexto). Às vezes, um sistema de arquivos com falha pode perder muitos inodes para erros. Ou talvez legitimamente, existem muitos arquivos. Este link deve informá-lo sobre arquivos e inodes. stackoverflow.com/questions/653096/howto-free-inode-usage, talvez seja necessário ver o que está sendo executado / aberto com o comando lsof.
J0h 03/07

Respostas:


23

Verifique se /lost+foundhouve um problema no disco e um monte de lixo eletrônico acabou sendo detectado como arquivos separados, possivelmente incorretamente.

Verifique iostatse algum aplicativo ainda está produzindo arquivos como um louco.

find / -xdev -type d -size +100kdirá se existe um diretório que use mais de 100kB de espaço em disco. Esse seria um diretório que contém muitos arquivos ou continha muitos arquivos no passado. Você pode ajustar a figura do tamanho.

Eu não acho que exista uma combinação de opções no GNU dupara fazer valer 1 por entrada no diretório. Você pode fazer isso produzindo a lista de arquivos finde contando um pouco no awk. Aqui está um dupara inodes. Minimamente testado, não tenta lidar com nomes de arquivos contendo novas linhas.

#!/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 /. Imprime uma lista de diretórios não vazios com a contagem total de entradas neles e seus subdiretórios recursivamente. Redirecione a saída para um arquivo e revise-a quando quiser. sort -k1nr <root.du-inodes | headlhe dirá os maiores infratores.


O script fornece erros: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, entendi, eu usei uma peculiaridade gawk que não funciona em outras versões. Eu adicionei uma barra invertida que considero necessária conforme POSIX.
Gilles 'SO- stop be evil'

14

Você pode verificar com este 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

Isso imprime os 10 principais subdiretórios por contagem de arquivos. Se você quer um x superior, mude headcom head -n x , onde xé um número natural maior que 0.

Para resultados 100% seguros, execute este script com privilégios de root:

pastas mais espessas


2019: levantou 10: read: Illegal option -d... esfregou a -dbandeira, readesperando que nada de ruim aconteça. Vou deixar você saber quando terminar de correr ...
Williams

3

Geralmente, mais rápido que a localização, se o banco de dados de localização estiver atualizado:

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

Isso despeja todo o banco de dados de localização, retira tudo do último '/' no caminho e, em seguida, a classificação e "uniq -c" fornecem o número de arquivos / diretórios por diretório. "sort -n" é direcionado para obter os dez diretórios com mais coisas neles.


+1: usar o banco de dados de localização é uma ótima idéia!
Max Beikirch

Quando você não puder usar o local por qualquer motivo, execute um find /path/to/parent -xdev > filelistprimeiro e, em seguida, direcione o sed para ler as entradas dessa lista.
Gerrit 16/08/19

1

Outra sugestão:

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

Use essas pesquisas para encontrar os maiores arquivos em seu servidor.

Encontre arquivos com mais de 1 GB

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

Encontre arquivos com mais de 100 MB

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

Encontre arquivos com mais de 10 MB

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

A primeira parte é o comando find usando o sinalizador "-size" para localizar arquivos em tamanhos diferentes, medidos em kilobytes.

O último bit no final, começando com "-exec", permite especificar um comando que queremos executar em cada arquivo encontrado. Aqui, o comando "ls -lh" inclui todas as informações exibidas ao listar o conteúdo de um diretório. O h no final é especialmente útil, pois imprime o tamanho de cada arquivo em um formato legível por humanos.


2
Seu problema é o alto uso de inodes, que aponta para muitos arquivos menores, e não grandes.
21715 Up UpCreek

0

Isso funcionou para mim quando o outro falhou no Android através do shell:

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

0

Eu gosto de usar algo como du --inodes -d 1 com o de encontrar um diretório que recursivamente ou diretamente contenha muitos arquivos.

Também gosto desta resposta: https://unix.stackexchange.com/a/123052

Para os preguiçosos, aqui está a essência:

du --inodes -S | sort -rh | sed -n \
    '1,50{/^.\{71\}/s/^\(.\{30\}\).*\(.\{37\}\)$/\1...\2/;p}'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.