Disco cheio mas df mostra espaço: Handles de arquivos deletados e exaustão de inodes
O que você vai aprender
- Por que você recebe
No space left on devicemesmo quandodfmostra espaço livre - Por que
dfreporta disco cheio mas o total dodué muito menor (ocupação por arquivo deletado) - Como dividir as duas direções da discrepância com
lsofedf -i, e recuperar espaço com segurança
Resumo rápido
df -hcheio masdué pequeno -> um processo mantém um arquivo deletado aberto. Encontre comlsof +L1, depois reinicie o serviço ou trunque o fddf -hmostra espaço mas escritas falham -> exaustão de inodes (verifiquedf -i) ou blocos reservados (não-root não consegue escrever)
Premissas (ambiente alvo)
- SO: Ubuntu / família Debian (ext4 assumido para
tune2fs) - Shell: bash
- Privilégios:
sudodisponível
Por que df discorda do espaço real livre?
Conclusão: df apenas lê os contadores agregados no superbloco do filesystem, então um inode deletado-mas-aberto ou uma tabela de inodes esgotada nunca aparece na porcentagem de capacidade.
df não percorre diretórios; ele lê os contadores que o filesystem mantém (blocos livres, inodes livres). du em vez disso percorre caminhos reais e soma seus tamanhos. Essa diferença de implementação é a raiz da discrepância, e aparece em três padrões típicos.
| Sintoma | Causa raiz | Comando |
|---|---|---|
df cheio, du pequeno |
Processo mantém arquivo deletado aberto | lsof +L1 |
df tem espaço, escritas falham |
Exaustão de inodes | df -i |
df mostra ~5% livre, não-root não escreve |
Blocos reservados | tune2fs -l |
A ideia chave: capacidade (blocos) e inodes são contadores separados. Esgote qualquer um deles e você recebe No space left on device.
Como verificar se um arquivo deletado está ocupando espaço?
Conclusão: lsof +L1 lista arquivos que ainda estão abertos mas têm link count de 0 (deletados); um SIZE grande em uma dessas linhas é exatamente o que causa a discrepância entre df e du.
Executar rm não libera um inode enquanto um processo ainda tem o arquivo aberto, então seus blocos nunca são recuperados. O caso clássico: um log foi deletado com rm, mas o serviço continua escrevendo nele.
$ sudo lsof +L1
+L1 mostra apenas arquivos abertos cujo link count está abaixo de 1 (ou seja, 0, deletado). Procure linhas onde NLINK é 0 e SIZE é grande.
Você também 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 mantém um log deletado de 8 GB aberto. O resultado: df está cheio, mas du /var/log parece pequeno.
Anote o PID e FD (aqui PID 1234 / FD 5). Você vai precisar deles no passo de liberação abaixo.
Como liberar o espaço mantido?
Conclusão: a correção limpa é reiniciar (ou recarregar) o processo ofensor. Se você precisa de espaço imediatamente, trunque /proc/PID/fd/N para zero bytes para recuperar sem reiniciar.
Opção A: reiniciar / recarregar o processo (recomendado)
Uma vez que o fd aberto é fechado, o inode é liberado e os blocos retornam instantaneamente.
$ sudo systemctl restart nginx
Para arquivos de log, muitos serviços reabrem seus arquivos no reload (systemctl reload nginx) em vez de um reinicio completo.
Opção B: truncar o fd quando não pode reiniciar
Se o serviço 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 são perdidos, mas o processo continua rodando e o espaço é recuperado imediatamente.
Somente trunque arquivos que são deletados E descartáveis (logs). Fazer isso em um arquivo de banco de dados ativo ou um arquivo real não deletado vai corrompê-lo. Confirme o marcador (deleted) com lsof +L1 primeiro.
Como verificar exaustão de inodes?
Conclusão: Quando df -i mostra IUse% em 100%, escritas falham mesmo com capacidade livre; localize o diretório com muitos arquivos pequenos usando find e faça limpeza.
Se df -h mostra espaço 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 exaustão de inodes. Encontre onde os muitos arquivos pequenos estão:
$ sudo find / -xdev -type f 2>/dev/null | cut -d/ -f1-3 | sort | uniq -c | sort -n | tail
Culpados comuns são arquivos de sessão, filas de email e fragmentos de cache (/var/lib/php/sessions, /var/spool, grandes quantidades de arquivos pequenos). Para limpeza detalhada, veja Corrigindo exaustão de inodes.
Por que df mostra ~5% livre mas escritas ainda falham?
Conclusão: ext4 reserva 5% dos blocos para root por padrão, então processos não-root recebem ENOSPC mesmo quando df mostra espaço livre; verifique e ajuste a reserva com tune2fs.
ext4 reserva 5% do filesystem para root por padrão (para manter o sistema recuperável). Aplicações não-root recebem ENOSPC mesmo quando df mostra espaço.
$ sudo tune2fs -l /dev/sda1 | grep -i 'reserved block'
Reserved block count: 6553600
Em uma partição somente de dados você pode reduzir a reserva para recuperá-la (não reduza muito no filesystem raiz):
$ sudo tune2fs -m 1 /dev/sda1
-m 1 define a reserva para 1%. Mantenha o padrão de 5% em /.
Como prevenir recorrência?
Conclusão: 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 verificações de rotina, não apenas df.
- Logs inchados: configure
logrotatecomcopytruncate, ou sinalize o serviço corretamente após rotação (nunca apenasrmno log ativo) - Monitoramento de inodes: adicione
df -iao monitoramento. Observar apenas capacidade (%) não detecta exaustão de inodes - Verificar antes de deletar: execute
lsof <arquivo>antes de remover um arquivo grande para ver quem o tem aberto
A rotina confiável é sempre olhar os três: df -h para capacidade, df -i para inodes, e lsof +L1 para ocupação por arquivo deletado.