FNSP Web Page

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 maior

O -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 -a

Quando 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/3

Aquilo 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/raiz

A 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 logrotate tem de avisar o processo. Rodar um registo sem enviar sinal nenhum é exatamente a receita do problema número 2 — daí existir a opção copytruncate para 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.

Comentários

Ainda ninguém comentou este artigo.

Voltar ao blog

Gostávamos de saber quantas pessoas visitam o site, com o Google Analytics. Sem a sua autorização não corre nada. Política de Privacidade.