Todos os artigos
149 artigos · atualizado semanalmente Veja nossas Ferramentas
Todos os artigos
Tutoriais

Como investigar falta de espaço em disco no Linux

Um método de diagnóstico para descobrir por que o disco está cheio: df para achar o mount, du para o diretório, e os casos que confundem como inodes e arquivos deletados.

Como investigar falta de espaço em disco no Linux
COVER · Tutoriais

O alerta chega sempre no pior momento: "no space left on device". O serviço para de subir, o banco recusa escrita, o deploy quebra no meio. A reação instintiva é abrir o servidor e sair apagando o que parecer descartável — log antigo, cache, aquele arquivo .tar.gz esquecido. É exatamente aí que você erra. Falta de espaço não se resolve por adivinhação; se resolve com método.

Este guia é sobre diagnóstico, não sobre uma lista de comandos soltos. O objetivo é responder à pergunta certa — "por que este disco está cheio?" — antes de tocar em qualquer arquivo. O foco é Linux em servidores, com atenção especial a /var/log, Docker e caches, que são onde o espaço some na prática.

Comece pelo mount, não pelo arquivo

O primeiro erro é pular direto para o du na raiz. Antes disso, você precisa saber qual filesystem está cheio. Um servidor típico tem vários mounts independentes: /, /var, /home, /boot, talvez um volume separado para Docker. Apagar arquivos em /home não adianta nada se quem encheu foi /var.

df -h

Leia a coluna Use% e a coluna Mounted on. O mount em 100% (ou perto disso) é o seu alvo. Anote o caminho — é a partir dele que toda a investigação continua. Se /boot estiver cheio, o problema quase sempre são kernels antigos; se for /, vale checar se Docker ou logs estão na raiz por falta de volume dedicado.

Um detalhe que confunde muita gente: o df -h reporta em base 1024 (MiB, GiB), enquanto o provedor de cloud vende o disco em base 1000 (MB, GB). Um "disco de 100 GB" aparece como ~93 GiB, e essa diferença de ~7% já basta para gerar pânico desnecessário quando alguém acha que "sumiram" gigabytes. Ao bater os números, converter as unidades entre base 1024 e base 1000 evita esse susto.

Desça com du a partir do mount culpado

Com o mount identificado, o du entra para apontar o diretório responsável. A chave é não rodar du na raiz do disco inteiro — isso é lento e despeja milhares de linhas. Rode com profundidade limitada, partindo do mount cheio, e ordene do maior para o menor.

du -h --max-depth=1 /var | sort -rh | head -20

A saída coloca o maior diretório no topo. Achou o culpado de primeiro nível (digamos, /var/lib/docker)? Repita descendo um nível:

du -h --max-depth=1 /var/lib/docker | sort -rh | head -20

Você desce assim, nível por nível, até chegar na pasta concreta que está estourando. É um método de bisseção: cada passo elimina metade do disco da suspeita. Em poucas iterações você sai de "o disco está cheio" para "são os logs de container em /var/lib/docker/containers".

Se preferir navegar interativamente em vez de repetir comandos, o ncdu é a melhor ferramenta para isso. Ele varre uma vez e te dá uma interface navegável por setas, com tamanhos já ordenados:

ncdu /var

Para a tarefa relacionada de listar os maiores arquivos individuais (e não diretórios), o método é um pouco diferente e merece atenção própria — cobri isso em como encontrar arquivos grandes no Linux. Aqui o foco continua sendo o diagnóstico de por que está cheio.

Quando o du não bate com o df

Este é o caso que faz gente boa perder uma hora. O df -h diz que o disco está em 95%, mas o du somando tudo dá muito menos. Os números não fecham. A explicação quase sempre é a mesma: um processo está com um arquivo aberto que já foi deletado do filesystem.

No Linux, quando você apaga um arquivo que ainda está aberto por um processo, o inode não é liberado até o processo fechar o descritor. O arquivo some do ls e do du — mas continua ocupando espaço, e o df ainda o conta. Clássico: alguém faz rm de um log de 20 GB que o serviço ainda está escrevendo.

lsof | grep deleted

A saída mostra qual processo segura o arquivo deletado e quanto ele ocupa. A solução não é apagar de novo (não há o que apagar) — é reiniciar ou sinalizar o processo para que ele libere o descritor. Em muitos serviços, um kill -HUP no PID basta para reabrir os arquivos de log; em outros, só um restart resolve. Depois disso, o espaço volta no df na hora.

Inodes esgotados com espaço sobrando

O oposto também acontece e é igualmente desconcertante: o df -h mostra espaço livre de sobra, mas a escrita falha mesmo assim com "no space left on device". O culpado aqui não é espaço — são inodes.

Cada arquivo, por menor que seja, consome um inode. Um filesystem tem um número fixo deles, definido na formatação. Se algo gera milhares e milhares de arquivos minúsculos — sessões PHP, caches de email, jobs de fila, arquivos temporários nunca limpos — você pode esgotar os inodes muito antes de esgotar os bytes.

df -i

A coluna IUse% em 100% confirma o diagnóstico. A partir daí, é du de novo, mas agora caçando quantidade de arquivos, não tamanho. Para contar arquivos por diretório, algo como for d in /var/*; do echo "$(find "$d" -type f | wc -l) $d"; done | sort -rn aponta o diretório com milhões de arquivos. A correção é apagar a horda de arquivos pequenos e, mais importante, descobrir o que os criou para parar a sangria.

Os suspeitos de sempre: logs, journald e Docker

Na prática, três fontes respondem pela maioria dos discos cheios em servidor.

/var/log e o journald. Logs sem rotação crescem indefinidamente. O journald do systemd, em particular, costuma ser configurado sem limite e engole gigabytes. Você pode aparar o journal sem mexer em arquivo manualmente:

journalctl --disk-usage
journalctl --vacuum-size=200M

Isso reduz o journal para 200 MB e descarta o resto. Para logs de aplicação, confira se o logrotate está ativo e configurado — log sem rotação é só questão de tempo até reaparecer aqui.

Docker. É o campeão silencioso. Imagens antigas, containers parados, volumes órfãos e build cache se acumulam em /var/lib/docker sem que ninguém perceba. O docker system df mostra o quanto cada categoria ocupa, e docker system prune -a --volumes limpa o que não está em uso — com cuidado, porque o --volumes apaga dados não referenciados. Logs de container também crescem sem teto se você não configurar log-opts com max-size no daemon.

Caches. Caches de gerenciadores de pacote (apt, yum), de build (npm, composer, pip) e de aplicação se acumulam. Eles são seguros de limpar, mas trate isso como alívio temporário, não como solução.

A diferença entre apagar e resolver

Aqui está a opinião que importa: limpar o disco não é o mesmo que resolver o problema. Se você rodou vacuum, deu prune e foi dormir, garanto que o alerta volta — em uma semana ou em um mês, mas volta. O disco encheu por uma causa, e essa causa continua lá.

Resolver significa fechar a torneira. Configure logrotate para todo log de aplicação. Defina limite no journald via SystemMaxUse no journalctl. Coloque max-size e max-file nos logs do Docker. Agende um docker system prune periódico. Monitore o disco com alerta em 80%, não em 100% — você quer descobrir antes do serviço cair, não depois. Diagnóstico bom evita o incêndio de hoje; configuração boa evita o de amanhã.

Perguntas frequentes

Por que o disco está cheio mas o du mostra pouco uso?

Quase sempre é um arquivo deletado que ainda está aberto por um processo. No Linux, o espaço só é liberado quando o último descritor de arquivo é fechado, então um log apagado que um serviço ainda escreve continua contando no df mas some do du. Rode lsof | grep deleted para achar o processo e reinicie-o ou envie kill -HUP para liberar o espaço.

Como descobrir o que está enchendo o /var?

Rode du -h --max-depth=1 /var | sort -rh | head -20 para ver qual subdiretório é o maior, e desça nível por nível repetindo o comando no diretório campeão. Os culpados habituais são /var/log (logs sem rotação), /var/lib/docker (imagens e containers) e /var/cache. O ncdu /var faz a mesma navegação de forma interativa.

O que fazer quando o df -i mostra 100% de inodes?

Você esgotou os inodes, não o espaço — geralmente por milhares de arquivos minúsculos como sessões, caches ou temporários. Localize o diretório com mais arquivos (não o maior em tamanho) contando entradas por pasta, apague a horda de arquivos pequenos e, principalmente, descubra o que os gera para impedir que voltem. Aumentar o número de inodes exige reformatar o filesystem, então a prevenção é o caminho.

journalctl --vacuum-size é seguro de rodar em produção?

Sim. Ele só descarta entradas antigas do journal até o tamanho que você definir, sem afetar serviços em execução nem perder logs recentes. Use journalctl --disk-usage antes para ver quanto está ocupado e, em seguida, configure SystemMaxUse no /etc/systemd/journald.conf para impor o limite permanentemente.

O que levar deste guia

Tenha um método e siga sempre na mesma ordem: df -h para achar o mount cheio, du (ou ncdu) descendo a partir dele para isolar o diretório, e só então a ação. Quando os números não baterem, lembre dos dois casos clássicos — arquivo deletado ainda aberto (lsof | grep deleted) e inodes esgotados (df -i). E quando o disco voltar a respirar, não pare por aí: configure rotação de log, limites no journald e no Docker, e um alerta em 80%. Diagnóstico tira você do aperto; configuração faz o aperto não voltar.

RD
Autor
Rafael Duarte
Desenvolvedor backend com passagem por fintech e SaaS B2B — trabalhou em times que escalaram APIs de zero a milhões de requisições. Carrega cicatrizes de produção suficientes para ter opiniões fortes sobre ferramentas, padrões e decisões de arquitetura. Não é acadêmico: leu a RFC do UUID quando precisou escolher entre v4 e v7 para uma tabela de alta escrita.
Ver perfil