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.
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.
- 01 TypeScript vale a pena em projetos pequenos? TS adiciona um build step, mas paga em autocompletar, refactor seguro e bugs pegos cedo. Veja o tradeoff real e quando NAO compensa em projeto pequeno.
- 02 Nameserver e zona DNS: qual é a diferença Trocar o nameserver não edita a sua zona DNS: muda onde ela vive e deixa os records para trás. Por isso o e-mail quebra. Entenda a diferença de uma vez.