Disco cheio e ninguém sabe porquê: as três armadilhas do espaço em Linux
O servidor pára, a aplicação começa a dar No space left on device, e o df confirma: 100%. Faz-se então a conta ao que lá está — e a conta não bate certo. O du soma metade do que o df diz estar ocupado.
Há três razões possíveis para essa diferença, e nenhuma delas é óbvia.
1. Primeiro, o trivial: onde está o espaço
df -h
# perceber qual das partições encheu
du -h -d1 /var | sort -h
# descer um nível de cada vez, seguindo a maiorO -d1 é o que torna isto suportável: em vez de somar a árvore inteira, mostra só o nível seguinte, e vai-se descendo pela linha maior. Quem tiver o ncdu instalado faz o mesmo com as setas, e é melhor.
Na maior parte das vezes acaba aqui, e o culpado é um dos suspeitos habituais:
journalctl --disk-usage
journalctl --vacuum-size=200M
docker system df
docker system prune -aQuando a conta bate certo, está resolvido. Quando não bate, é porque se caiu numa das três.
2. O ficheiro apagado que continua a ocupar espaço
Esta é a mais frequente e a menos conhecida. O du percorre nomes — anda pelas pastas e soma o que encontra. O df pergunta ao sistema de ficheiros quantos blocos estão em uso.
Um ficheiro apagado enquanto um processo o tinha aberto deixa de ter nome, mas não desaparece: os blocos só são libertados quando o último descritor fechar. O du deixa de o ver. O df continua a contá-lo.
O caso clássico é um registo que alguém apagou à mão, ou uma rotação mal configurada, com o processo a continuar a escrever para um ficheiro que já não tem nome:
lsof +L1
# COMMAND PID USER FD TYPE DEVICE SIZE NLINK NAME
# nginx 1234 root 3w REG 8,1 42949672960 0 /var/log/nginx/access.log (deleted)O +L1 pede exatamente isto: ficheiros abertos com menos de uma ligação, ou seja, sem nome. A coluna NLINK a zero é a confirmação.
A solução óbvia é reiniciar o processo. Quando isso não é possível — e num servidor a sério muitas vezes não é —, há outra saída: escrever zero bytes através do descritor que ainda está aberto.
: > /proc/1234/fd/3Aquilo esvazia o ficheiro sem o fechar. O espaço volta na hora, o processo continua a escrever, e ninguém teve de ir abaixo. É o comando que mais vezes me safou, e quase nunca aparece nas respostas habituais.
3. Há espaço, e mesmo assim não escreve
O df -h mostra 60% ocupado e o sistema insiste que o disco está cheio. Falta perguntar pela outra coisa que se esgota:
df -i
# Filesystem Inodes IUsed IFree IUse% Mounted on
# /dev/sda1 1310720 1310718 2 100% /Cada ficheiro consome um inode, e um sistema de ficheiros tem um número fixo deles, decidido quando foi formatado. Milhões de ficheiros minúsculos — sessões, cache, mensagens em fila — esgotam os inodes muito antes de esgotarem os gigabytes.
O sintoma é enganador porque toda a gente olha para o -h e ninguém olha para o -i. E a correção é diferente: apagar ficheiros grandes não ajuda nada; é preciso apagar muitos ficheiros.
4. O que ficou escondido por baixo de um ponto de montagem
A terceira é rara mas desespera quem a apanha. Se alguma coisa escreveu em /mnt/dados antes de o disco ser montado ali, esses ficheiros continuam na partição de origem — tapados pela montagem, invisíveis a qualquer du.
mount --bind / /mnt/raiz
du -sh /mnt/raiz/mnt/dados
umount /mnt/raizA montagem em modo bind dá uma segunda vista da raiz, desta vez sem nada por cima. É ali que aparecem os ficheiros que ninguém conseguia encontrar.
5. Depois de resolver, evitar
O
logrotatetem de avisar o processo. Rodar um registo sem enviar sinal nenhum é exatamente a receita do problema número 2 — daí existir a opçãocopytruncatepara os programas que não sabem reabrir o ficheiro.Vigiar aos 80%, não aos 100%. Entre os 80 e os 100 há tempo para agir; depois dos 100 já não se consegue sequer escrever o ficheiro temporário de que muitas ferramentas precisam para arrumar seja o que for.
Limitar o journal por configuração, com
SystemMaxUse, em vez de o esvaziar à mão de seis em seis meses.
O resumo
Se o du e o df discordam, a resposta está quase sempre num ficheiro apagado que alguém ainda tem aberto — e o lsof +L1 mostra-o em dois segundos. Se concordam e mesmo assim não escreve, é o df -i que falta correr. E se nada disso explicar, então há coisas escondidas debaixo de uma montagem.