Disco cheio mas df mostra espaco: Handles de arquivos deletados e exaustao de inodes
O que voce vai aprender
- Por que voce recebe
No space left on devicemesmo quandodfmostra espaco livre - Por que
dfreporta disco cheio mas o total dodue muito menor (ocupacao por arquivo deletado) - Como dividir as duas direcoes da discrepancia com
lsofedf -i, e recuperar espaco com seguranca
Resumo rapido
df -hcheio masdue pequeno -> um processo mantem um arquivo deletado aberto. Encontre comlsof +L1, depois reinicie o servico ou trunque o fddf -hmostra espaco mas escritas falham -> exaustao de inodes (verifiquedf -i) ou blocos reservados (nao-root nao consegue escrever)
Premissas (ambiente alvo)
- SO: Ubuntu / familia Debian (ext4 assumido para
tune2fs) - Shell: bash
- Privilegios:
sudodisponivel
Por que df discorda do espaco real livre?
Conclusao: df apenas le os contadores agregados no superbloco do filesystem, entao um inode deletado-mas-aberto ou uma tabela de inodes esgotada nunca aparece na porcentagem de capacidade.
df nao percorre diretorios; ele le os contadores que o filesystem mantem (blocos livres, inodes livres). du em vez disso percorre caminhos reais e soma seus tamanhos. Essa diferenca de implementacao e a raiz da discrepancia, e aparece em tres padroes tipicos.
| Sintoma | Causa raiz | Comando |
|---|---|---|
df cheio, du pequeno |
Processo mantem arquivo deletado aberto | lsof +L1 |
df tem espaco, escritas falham |
Exaustao de inodes | df -i |
df mostra ~5% livre, nao-root nao escreve |
Blocos reservados | tune2fs -l |
A ideia chave: capacidade (blocos) e inodes sao contadores separados. Esgote qualquer um deles e voce recebe No space left on device.
Como verificar se um arquivo deletado esta ocupando espaco?
Conclusao: lsof +L1 lista arquivos que ainda estao abertos mas tem link count de 0 (deletados); um SIZE grande em uma dessas linhas e exatamente o que causa a discrepancia entre df e du.
Executar rm nao libera um inode enquanto um processo ainda tem o arquivo aberto, entao seus blocos nunca sao recuperados. O caso classico: um log foi deletado com rm, mas o servico continua escrevendo nele.
$ sudo lsof +L1
+L1 mostra apenas arquivos abertos cujo link count esta abaixo de 1 (ou seja, 0, deletado). Procure linhas onde NLINK e 0 e SIZE e grande.
Voce tambem pode fazer grep pelo marcador deleted:
$ sudo lsof -nP / 2>/dev/null | grep '(deleted)'
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nginx 1234 root 5w REG 259,1 8589934592 131 /var/log/nginx/access.log (deleted)
Aqui o nginx ainda mantem um log deletado de 8 GB aberto. O resultado: df esta cheio, mas du /var/log parece pequeno.
Anote o PID e FD (aqui PID 1234 / FD 5). Voce vai precisar deles no passo de liberacao abaixo.
Como liberar o espaco mantido?
Conclusao: a correcao limpa e reiniciar (ou recarregar) o processo ofensor. Se voce precisa de espaco imediatamente, trunque /proc/PID/fd/N para zero bytes para recuperar sem reiniciar.
Opcao A: reiniciar / recarregar o processo (recomendado)
Uma vez que o fd aberto e fechado, o inode e liberado e os blocos retornam instantaneamente.
$ sudo systemctl restart nginx
Para arquivos de log, muitos servicos reabrem seus arquivos no reload (systemctl reload nginx) em vez de um reinicio completo.
Opcao B: truncar o fd quando nao pode reiniciar
Se o servico deve permanecer ativo, trunque o arquivo ainda aberto via /proc/<PID>/fd/<FD>.
$ sudo truncate -s 0 /proc/1234/fd/5
: > /proc/1234/fd/5 faz o mesmo. Os dados sao perdidos, mas o processo continua rodando e o espaco e recuperado imediatamente.
Somente trunque arquivos que sao deletados E descartaveis (logs). Fazer isso em um arquivo de banco de dados ativo ou um arquivo real nao deletado vai corrompe-lo. Confirme o marcador (deleted) com lsof +L1 primeiro.
Como verificar exaustao de inodes?
Conclusao: Quando df -i mostra IUse% em 100%, escritas falham mesmo com capacidade livre; localize o diretorio com muitos arquivos pequenos usando find e faca limpeza.
Se df -h mostra espaco mas escritas ainda falham, suspeite de inodes.
$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on /dev/sda1 6553600 6553600 0 100% /
IUse% em 100% significa exaustao de inodes. Encontre onde os muitos arquivos pequenos estao:
$ sudo find / -xdev -type f 2>/dev/null | cut -d/ -f1-3 | sort | uniq -c | sort -n | tail
Culpados comuns sao arquivos de sessao, filas de email e fragmentos de cache (/var/lib/php/sessions, /var/spool, grandes quantidades de arquivos pequenos). Para limpeza detalhada, veja Corrigindo exaustao de inodes.
Por que df mostra ~5% livre mas escritas ainda falham?
Conclusao: ext4 reserva 5% dos blocos para root por padrao, entao processos nao-root recebem ENOSPC mesmo quando df mostra espaco livre; verifique e ajuste a reserva com tune2fs.
ext4 reserva 5% do filesystem para root por padrao (para manter o sistema recuperavel). Aplicacoes nao-root recebem ENOSPC mesmo quando df mostra espaco.
$ sudo tune2fs -l /dev/sda1 | grep -i 'reserved block'
Reserved block count: 6553600
Em uma particao somente de dados voce pode reduzir a reserva para recupera-la (nao reduza muito no filesystem raiz):
$ sudo tune2fs -m 1 /dev/sda1
-m 1 define a reserva para 1%. Mantenha o padrao de 5% em /.
Como prevenir recorrencia?
Conclusao: Rotacione logs com logrotate copytruncate ou um hook de reload correto para que arquivos sejam reabertos, e monitore inodes; adicione df -i e lsof +L1 as suas verificacoes de rotina, nao apenas df.
- Logs inchados: configure
logrotatecomcopytruncate, ou sinalize o servico corretamente apos rotacao (nunca apenasrmno log ativo) - Monitoramento de inodes: adicione
df -iao monitoramento. Observar apenas capacidade (%) nao detecta exaustao de inodes - Verificar antes de deletar: execute
lsof <arquivo>antes de remover um arquivo grande para ver quem o tem aberto
A rotina confiavel e sempre olhar os tres: df -h para capacidade, df -i para inodes, e lsof +L1 para ocupacao por arquivo deletado.