Encontre onde os inodes estão sendo usados

189

Por isso, recebi um aviso do nosso sistema de monitoramento em uma de nossas caixas informando que o número de inodes livres em um sistema de arquivos estava ficando baixo.

df -i A saída mostra isso:

Filesystem       Inodes  IUsed    IFree IUse% Mounted on
/dev/xvda1       524288 422613   101675   81% /

Como você pode ver, a partição raiz possui 81% de seus inodes usados.
Eu suspeito que todos eles estão sendo usados ​​em um único diretório. Mas como posso descobrir onde é isso?

Patrick
fonte

Respostas:

214

Eu vi essa pergunta no stackoverflow, mas não gostei de nenhuma das respostas, e é realmente uma pergunta que deveria estar aqui no U&L de qualquer maneira.

Basicamente, um inode é usado para cada arquivo no sistema de arquivos. Portanto, ficar sem inodes geralmente significa que você tem muitos arquivos pequenos por aí. Portanto, a pergunta realmente se torna: "qual diretório tem um grande número de arquivos?"

Nesse caso, o sistema de arquivos com o qual nos preocupamos é o sistema de arquivos raiz /, para que possamos usar o seguinte comando:

find / -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n

Isso irá despejar uma lista de todos os diretórios no sistema de arquivos prefixados com o número de arquivos (e subdiretórios) nesse diretório. Assim, o diretório com o maior número de arquivos estará na parte inferior.

No meu caso, isso mostra o seguinte:

   1202 /usr/share/man/man1
   2714 /usr/share/man/man3
   2826 /var/lib/dpkg/info
 306588 /var/spool/postfix/maildrop

Então, basicamente, /var/spool/postfix/maildropestá consumindo todos os inodes.

Observe que esta resposta tem três advertências em que consigo pensar. Ele não lida corretamente com nada com novas linhas no caminho. Sei que meu sistema de arquivos não possui arquivos com novas linhas e, como isso está sendo usado apenas para consumo humano, não vale a pena solucionar o problema em potencial (e sempre é possível substituir o \npor \0e usar sort -zacima). Ele também não controla se os arquivos estão espalhados por um grande número de diretórios. Isso não é provável, então considero o risco aceitável. Ele também contará links físicos para o mesmo arquivo (portanto, usando apenas um inode) várias vezes. Mais uma vez, é improvável que dê falsos positivos


A principal razão pela qual não gostei de nenhuma das respostas na resposta do stackoverflow é que todas elas cruzam os limites do sistema de arquivos. Como meu problema estava no sistema de arquivos raiz, isso significa que ele atravessaria todos os sistemas de arquivos montados. Jogar -xdevos comandos find nem funcionaria corretamente.
Por exemplo, a resposta mais votada é esta:

for i in `find . -type d `; do echo `ls -a $i | wc -l` $i; done | sort -n

Se mudarmos isso para

for i in `find . -xdev -type d `; do echo `ls -a $i | wc -l` $i; done | sort -n

mesmo que /mnt/fooseja uma montagem, também é um diretório no sistema de arquivos raiz; portanto, ele aparece find . -mount -type de é passado para o ls -a $i, que entrará na montagem.

Em findminha resposta, em vez disso, lista o diretório de cada arquivo na montagem. Então, basicamente, com uma estrutura de arquivos como:

/foo/bar
/foo/baz
/pop/tart

acabamos com

/foo
/foo
/pop

Então, apenas precisamos contar o número de linhas duplicadas.

Patrick
fonte
2
@MohsenPahlevanzadeh que não faz parte da minha resposta, eu estava comentando por que não gosto da solução, pois é uma resposta comum a esta pergunta.
267 Patrick Patrick
7
O uso de uma montagem de ligação é uma maneira mais robusta de evitar a pesquisa em outros sistemas de arquivos, pois permite o acesso a arquivos sob pontos de montagem. Por exemplo, imagine que eu crie 300.000 arquivos abaixo /tmpe depois o sistema esteja configurado para montar um tmpfs /tmp. Então você não poderá encontrar os arquivos findsozinho. Senario improvável, mas vale a pena notar.
Graeme
2
Ambos os trabalhos tiveram que remover a classificação porque a classificação precisa criar um arquivo quando a saída é grande o suficiente, o que não era possível desde que atingi 100% do uso de inodes.
Qwertzguy
11
Observe que -printfparece ser uma extensão GNU a ser encontrada, pois a versão BSD disponível no OS X não a suporta.
Xiong Chiamiov
11
A suposição de que todos os arquivos estão em um único diretório é difícil. Muitos programas sabem que muitos arquivos em um único diretório têm desempenho ruim e, portanto
fazem o
26

Isso é publicado aqui a pedido do autor:

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

E se você quiser permanecer no mesmo sistema de arquivos, faça:

du --inodes -xS

Aqui está um exemplo de saída:

15K     /usr/share/man/man3
4.0K    /usr/lib
3.6K    /usr/bin
2.4K    /usr/share/man/man1
1.9K    /usr/share/fonts/75dpi
...
519     /usr/lib/python2.7/site-packages/bzrlib
516     /usr/include/KDE
498     /usr/include/qt/QtCore
487     /usr/lib/modules/3.13.6-2-MANJARO/build/include/config
484     /usr/src/linux-3.12.14-2-MANJARO/include/config

AGORA COM LS:

Várias pessoas mencionaram que não possuem coreutils atualizados e a opção --inodes não está disponível para eles. Então, aqui está o sl:

ls ~/test -AiR1U | 
sed -rn '/^[./]/{h;n;};G;
    s|^ *([0-9][0-9]*)[^0-9][^/]*([~./].*):|\1:\2|p' | 
sort -t : -uk1.1,1n |
cut -d: -f2 | sort -V |
uniq -c |sort -rn | head -n10

Se você estiver curioso, o coração e a alma desse pedaço tedioso regexestão substituindo os resultados de pesquisa recursivos filenameem cada um dos ls'sresultados pelo nome do diretório em que foram encontrados. A partir daí, é apenas uma questão de espremer números de inodes repetidos e, em seguida, contar nomes de diretórios repetidos e classificar de acordo.

A -Uopção é especialmente útil na classificação em que ela especificamente não é classificada e, em vez disso, apresenta a lista de diretórios na ordem original - ou, em outras palavras, pelo inodenúmero.

E, -1é claro, é incrivelmente útil, pois garante um único resultado por linha, independentemente de novas linhas possivelmente incluídas nos nomes de arquivos ou outros problemas espetacularmente infelizes que podem ocorrer quando você tenta analisar uma lista.

E, é claro, -Apara todos, -ipara o inode e -Rpara o recursivo, e esse é o longo e curto disso.

O método subjacente a isso é que eu substituo todos os nomes de arquivos de ls pelo seu nome de diretório que contém sed. Na sequência disso ... Bem, estou um pouco confusa. Tenho certeza de que está contando com precisão os arquivos, como você pode ver aqui:

% _ls_i ~/test
> 100 /home/mikeserv/test/realdir
>   2 /home/mikeserv/test
>   1 /home/mikeserv/test/linkdir

Isso está me fornecendo resultados praticamente idênticos ao ducomando:

DU:

15K     /usr/share/man/man3
4.0K    /usr/lib
3.6K    /usr/bin
2.4K    /usr/share/man/man1
1.9K    /usr/share/fonts/75dpi
1.9K    /usr/share/fonts/100dpi
1.9K    /usr/share/doc/arch-wiki-markdown
1.6K    /usr/share/fonts/TTF
1.6K    /usr/share/dolphin-emu/sys/GameSettings
1.6K    /usr/share/doc/efl/html

LS:

14686   /usr/share/man/man3:
4322    /usr/lib:
3653    /usr/bin:
2457    /usr/share/man/man1:
1897    /usr/share/fonts/100dpi:
1897    /usr/share/fonts/75dpi:
1890    /usr/share/doc/arch-wiki-markdown:
1613    /usr/include:
1575    /usr/share/doc/efl/html:
1556    /usr/share/dolphin-emu/sys/GameSettings:

Eu acho que a includecoisa depende apenas de qual diretório o programa parece primeiro - porque eles são os mesmos arquivos e têm links físicos. Tipo como a coisa acima. Eu posso estar errado sobre isso - e congratulo-me com a correção ...

DU DEMO

% du --version
> du (GNU coreutils) 8.22

Faça um diretório de teste:

% mkdir ~/test ; cd ~/test
% du --inodes -S
> 1       .

Alguns diretórios filhos:

% mkdir ./realdir ./linkdir
% du --inodes -S
> 1       ./realdir
> 1       ./linkdir
> 1       .

Faça alguns arquivos:

% printf 'touch ./realdir/file%s\n' `seq 1 100` | . /dev/stdin
% du --inodes -S
> 101     ./realdir
> 1       ./linkdir
> 1       .

Alguns hardlinks:

% printf 'n="%s" ; ln ./realdir/file$n ./linkdir/link$n\n' `seq 1 100` | 
    . /dev/stdin
% du --inodes -S
> 101     ./realdir
> 1       ./linkdir
> 1       .

Veja os hardlinks:

% cd ./linkdir
% du --inodes -S
> 101

% cd ../realdir
% du --inodes -S
> 101

Eles são contados sozinhos, mas sobe um diretório ...

% cd ..
% du --inodes -S
> 101     ./realdir
> 1       ./linkdir
> 1       .

Em seguida, executei meu script de baixo e:

> 100     /home/mikeserv/test/realdir
> 100     /home/mikeserv/test/linkdir
> 2       /home/mikeserv/test

E Graeme's:

> 101 ./realdir
> 101 ./linkdir
> 3 ./

Então, acho que isso mostra que a única maneira de contar inodes é por inode. E como contar arquivos significa contar inodes, você não pode contar inodes duplamente - contar arquivos com inodes com precisão não pode ser contado mais de uma vez.

mikeserv
fonte
2
qual versão foi adicionada --inodes? quais "variantes" / "sabores" / "posix-wannabes" / "implementações" / o que quer que seja?
N611x007
Ubuntu 14.04.5: du: opção não reconhecida '--inodes'
Putnik
du (GNU coreutils) 8.23 ​​de 2014 possui (está no meu desatualizado Debian Jessie). Debian> Ubuntu desculpe o trocadilho: P Ubuntu tem pacotes tão antigos ...
Daniel W.
6

Eu usei esta resposta da SO Q&A intitulada: Onde estão sendo usados ​​todos os meus inodes? quando nosso NAS acabou há cerca de 2 anos:

$ find . -type d -print0 \
    | while IFS= read -rd '' i; do echo $(ls -a "$i" | wc -l) "$i"; done \
    | sort -n

Exemplo

$ find . -type d -print0 \
    | while IFS= read -rd '' i; do echo $(ls -a "$i" | wc -l) "$i"; done \
    | sort -n
...
110 ./MISC/nodejs/node-v0.8.12/out/Release/obj.target/v8_base/deps/v8/src
120 ./MISC/nodejs/node-v0.8.12/doc/api
123 ./apps_archive/monitoring/nagios/nagios-check_sip-1.3/usr/lib64/nagios
208 ./MISC/nodejs/node-v0.8.12/deps/openssl/openssl/doc/crypto
328 ./MISC/nodejs/node-v0.8.12/deps/v8/src
453 ./MISC/nodejs/node-v0.8.12/test/simple

Verificando os inodes do dispositivo

Dependendo do seu NAS, ele pode não oferecer um dfcomando completo . Portanto, nesses casos, você pode recorrer ao uso tune2fs:

$ sudo tune2fs -l /dev/sda1 |grep -i inode
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super huge_file uninit_bg dir_nlink extra_isize
Inode count:              128016
Free inodes:              127696
Inodes per group:         2032
Inode blocks per group:   254
First inode:              11
Inode size:           128
Journal inode:            8
Journal backup:           inode blocks

Cruzando os limites do sistema de arquivos

Você pode usar a -xdevopção para direcionar findpara restringir sua pesquisa apenas ao dispositivo em que você está iniciando a pesquisa.

Exemplo

Digamos que eu tenha minha /homemontagem automática de diretório por meio de compartilhamentos NFS do meu NAS, cujo nome é mulder.

$ df -h /home/sam 
Filesystem            Size  Used Avail Use% Mounted on
mulder:/export/raid1/home/sam
                      917G  572G  299G  66% /home/sam

Observe que o ponto de montagem ainda é considerado local para o sistema.

$ df -h /home/ .
Filesystem            Size  Used Avail Use% Mounted on
-                        0     0     0   -  /home
/dev/mapper/VolGroup00-LogVol00
                      222G  159G   52G  76% /

Agora, quando inicio find:

$ find / -xdev  | grep '^/home'
/home

Ele encontrou /homemas nenhum conteúdo montado automaticamente porque está em um dispositivo diferente!

Tipos de sistema de arquivos

Você pode utilizar a opção para find, -fstypepara controlar quais tipos de sistemas de arquivos findserão analisados.

   -fstype type
          File is on a filesystem of type type.  The valid filesystem types 
          vary among different versions of Unix; an incomplete list of 
          filesystem  types that are accepted on some version of Unix or 
          another is: ufs, 4.2, 4.3, nfs, tmp, mfs, S51K, S52K.  You can use 
          -printf with the %F directive to see the types of your
          filesystems.

Exemplo

Que sistema de arquivos eu tenho?

$ find . -printf "%F\n" | sort -u
ext3

Então você pode usar isso para controlar o cruzamento:

somente ext3

$ find . -fstype ext3 | head -5
.
./gdcm
./gdcm/gdcm-2.0.16
./gdcm/gdcm-2.0.16/Wrapping
./gdcm/gdcm-2.0.16/Wrapping/CMakeLists.txt

somente nfs

$ find . -fstype nfs | head -5
$ 

ext3 e ext4

$ find . -fstype ext3 -o -fstype ext4 | head -5
.
./gdcm
./gdcm/gdcm-2.0.16
./gdcm/gdcm-2.0.16/Wrapping
./gdcm/gdcm-2.0.16/Wrapping/CMakeLists.txt
slm
fonte
Qual seria sua solução para impedir que ela cruzasse os limites do sistema de arquivos? Como se /está cheio, e você tem sistemas de arquivos de rede montados, não deseja mergulhar nos sistemas de arquivos de rede.
267 Patrick Patrick
@Patrick - veja as atualizações, você pode controlá-lo usando -fstypea find.
slm
11
@Gilles - resposta simples ... não paginei a página de manual do find 8-)
slm
@Gilles - a página do manual não parece indicar que -xtypeexclui os sistemas de arquivos, mas sim o tipo de arquivo. Só estou encontrando exemplos como este:find . \( -fstype nfs -prune \)
slm
@ Gilles - eu estava abordando o Q de Patrick nos comentários sobre como evitar findcruzar os limites do sistema de arquivos. Em seu ex. ele menciona "Como se / está cheio, e você tem sistemas de arquivos de rede montados, você não quer mergulhar nos sistemas de arquivos de rede".
slm
4

Comando para encontrar o inode usado:

for i in /*; do echo $i; find $i |wc -l | sort ; done
Ashish Karpe
fonte
3

Para listar o uso detalhado do inode /, use o seguinte comando:

echo "Detailed Inode usage for: $(pwd)" ; for d in `find -maxdepth 1 -type d |cut -d\/ -f2 |grep -xv . |sort`; do c=$(find $d |wc -l) ; printf "$c\t\t- $d\n" ; done ; printf "Total: \t\t$(find $(pwd) | wc -l)\n" 
user108434
fonte
Bem vindo aqui! Sugiro que, da próxima vez, formato melhor, por favor.
Peterh
11
É um delineador, não vejo nada de errado nisso.
S18 /
2

Definitivamente, responda com upvotes máximos para ajudar a entender o conceito de inodes no linux e no unix, no entanto, não ajuda muito quando se trata de lidar com o problema real de excluir ou remover os inodes do disco. Uma maneira mais simples de fazer isso em sistemas baseados no ubuntu é remover cabeçalhos e imagens indesejados do kernel do linux.

sudo apt-get autoremove

Faria isso por você. No meu caso, o uso de inodes foi de 78%, devido ao qual recebi um alerta.

$ df -i
Filesystem     Inodes  IUsed  IFree IUse% Mounted on
/dev/xvda1     524288 407957 116331   78% /
none           957443      2 957441    1% /sys/fs/cgroup
udev           956205    388 955817    1% /dev
tmpfs          957443    320 957123    1% /run
none           957443      1 957442    1% /run/lock
none           957443      1 957442    1% /run/shm
none           957443      5 957438    1% /run/user

Depois de executar o sudo apt-get autoremovecomando, ele caiu para 29%

$ df -i
Filesystem     Inodes  IUsed  IFree IUse% Mounted on
/dev/xvda1     524288 150472 373816   29% /
none           957443      2 957441    1% /sys/fs/cgroup
udev           956205    388 955817    1% /dev
tmpfs          957443    320 957123    1% /run
none           957443      1 957442    1% /run/lock
none           957443      1 957442    1% /run/shm
none           957443      5 957438    1% /run/user

Esta foi apenas a minha observação que economizou meu tempo. As pessoas podem encontrar uma solução melhor que essa.

Shailesh Sutar
fonte
2

Acho que é mais rápido e fácil fazer uma busca detalhada usando o seguinte comando:

$ sudo du -s --inodes * | sort -rn

170202  var
157325  opt
103134  usr
53383   tmp
<snip>

Você pode então acessar, varpor exemplo, e ver qual é o grande inode usando diretórios.

JonoB
fonte
0

Até agora, todas as respostas assumem que o problema ocorre com muitos arquivos em um único diretório, em vez de muitos subdiretórios, todos contribuindo para o problema. Felizmente, a solução é simplesmente usar menos sinalizadores.

# du --inodes --one-file-system /var | sort --numeric-sort
...
2265    /var/cache/salt/minion
3818    /var/lib/dpkg/info
3910    /var/lib/dpkg
4000    /var/cache/salt/master/gitfs/refs
4489    /var/lib
5709    /var/cache/salt/master/gitfs/hash
12954   /var/cache/salt/master/gitfs
225058  /var/cache/salt/master/jobs
241678  /var/cache/salt/master
243944  /var/cache/salt
244078  /var/cache
248949  /var

Ou com opções mais curtas: du --inodes -x | sort -n. Infelizmente nem todas as versões dupossuem a opção inodes.

OrangeDog
fonte