lsof: Ficheiros Abertos, Portas e Diagnóstico no Linux
Neste artigo:
- Instalar o lsof
- Ler a saída: as colunas COMMAND, PID, USER, FD, TYPE e NAME
- Quem abre este ficheiro: caminho e directórios (+D)
- Quem segura a porta 8080: -i, protocolos e estados TCP
- O que este processo tem aberto: -p, -c e -g
- Ficheiros apagados que continuam a gastar disco
- Sockets Unix, NFS e o que o lsof conta como ficheiro
- Quando o lsof trava: NFS inacessível, -b e -S
- Scripts: -t, exit code e o pipeline com wc
- Diagnóstico de segurança com o lsof
- Erros Comuns
- Checklist
- Artigos Relacionados
- Fontes Oficiais
Todos os dias o disco enche e o df aponta para um directório onde o ls não mostra nada. Ou a porta 8080 devolve “address already in use” e não há serviço nenhum à vista com ps. Ou um umount falha com “target is busy” sem ninguém admitir estar a usar o disco. As três perguntas têm a mesma resposta: um processo tem qualquer coisa aberta que os comandos comuns não mostram. No Linux, tudo o que um processo tem aberto — ficheiros regulares, directórios, bibliotecas, sockets TCP e UDP, pipes — vive na tabela de descritores do processo, e o comando que a lê é o lsof (LiSt Open Files).
O lsof vem nos repositórios de todas as distribuições principais: o Debian 12 traz a versão 4.95.0 e o Debian 13 a 4.99.4 (packages.debian.org, trixie), e o Ubuntu 24.04 LTS segue a mesma série (packages.ubuntu.com). O projecto é mantido pela equipa lsof-org no GitHub, que assumiu o código de Vic Abell, e a referência é a man page lsof(8). Este guia parte de um Debian 12/13 ou Ubuntu LTS, instala o pacote e percorre as perguntas de diagnóstico pela ordem em que aparecem: quem abre um ficheiro, quem segura uma porta, o que um processo tem aberto, os ficheiros apagados que gastam disco, e o exit code para scripts.
1. Instalar o lsof
sudo apt update
sudo apt install lsof
lsof -v
O lsof -v imprime a revisão compilada no binário — em Debian 13, a 4.99.4. Nalgumas instalações mínimas (contentores, imagens de cloud) o pacote não vem de origem. Sem ele, os sintomas acima ficam sem resposta porque ss e lsof respondem a perguntas diferentes: o ss lista os sockets que existem, o lsof liga cada socket e cada ficheiro ao processo que o detém.
2. Ler a saída: as colunas COMMAND, PID, USER, FD, TYPE e NAME
O primeiro passo é ler a tabela que o lsof imprime. Um exemplo do manual:
sudo lsof /var/log/wtmp
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root 9u REG 8,1 273408 631 /var/log/wtmp
- COMMAND são os primeiros nove caracteres do nome do comando (o
+c 0imprime o nome completo, até ao limite que o kernel devolve). - FD é o descritor: um número (0=stdin, 1=stdout, 2=stderr), ou uma abreviatura —
cwd(directório actual),rtd(raiz),txt(código do programa),mem(ficheiro mapeado em memória). A letra a seguir do número é o modo de abertura:rleitura,wescrita,uleitura e escrita. - TYPE distingue
REG(ficheiro regular),DIR,CHR,FIFO,unixe os sockets de rede. - NAME fecha a linha: para sockets de rede mostra
local:porta->remoto:porta, e o estado TCP aparece em parênteses, como(ESTABLISHED).
Sem opções, o lsof lista todos os ficheiros abertos por todos os processos — saída de milhares de linhas num servidor cheio. As opções seguintes existem para filtrar essa tabela.
3. Quem abre este ficheiro: caminho e directórios (+D)
A pergunta mais directa é responder com o caminho do ficheiro. O tutorial oficial usa exatamente este caso:
lsof /etc/passwd
O caminho funciona por equivalência de dispositivo e inode — um ficheiro renomeado entre a abertura e a consulta continua a ser encontrado. Para um sistema de ficheiros inteiro (a pergunta clássica do umount), o nome do ponto de montagem lista tudo o que está aberto nele:
lsof /mnt/dados
Para “quem está a usar algo dentro deste directório?”, há duas formas de busca em árvore:
lsof +D /var/log
- O
+Ddesce a árvore completa a partir do directório, fazstat(2)a cada ficheiro e cruza o resultado com a tabela de ficheiros abertos. - O
+d(minúsculo) olha apenas para o nível de topo do directório. - O manual avisa expressamente: o
+Dpode ser lento e exigir bastante memória em directórios grandes, porque percorre a árvore inteira — em/é uma operação a evitar. Para o disco inteiro, o caminho do sistema de ficheiros (lsof /) faz o mesmo trabalho sem construir a lista de ficheiros. - O
+Dnão segue symbolic links nem atravessa pontos de montagem dentro da árvore, a não ser que se junte-x.
4. Quem segura a porta 8080: -i, protocolos e estados TCP
A gramática do -i é [46][protocolo][@anfitrião][:porta], e cobre as perguntas de rede mais comuns:
lsof -i :8080
lsof -iTCP -sTCP:LISTEN
lsof -iUDP
lsof [email protected]
lsof -i :8080responde a “quem tem esta porta” — para TCP e UDP ao mesmo tempo. Elsof -iTCP:8080restringe ao protocolo TCP.lsof -iTCP -sTCP:LISTENlista só os sockets à escuta: é o inventário de portas abertas do servidor, com o processo responsável por cada uma. O-sTCP:aceita os nomes de estado TCP —LISTEN,ESTABLISHED,SYN_SENT,CLOSE_WAIT,TIME_WAIT, entre outros — e o^inverte (por exemplo, tudo menosESTABLISHED).- O
@anfitriãofiltra a outra ponta da ligação — útil para responder “que ligações existem para este endereço”. lsof -i4elsof -i6separam IPv4 de IPv6.
Duas bandeiras deixam a saída mais rápida: -P impede a conversão de números de porta para nomes de serviço (a tabela /etc/services) e -n impede a resolução de endereços para nomes. Ambas tornam o comando mais rápido e evitam esperas quando o DNS não responde — num servidor com DNS degradado, lsof -nP -i é a forma que não bloqueia.
O -i é também a resposta a “há algum serviço aqui que eu não conheço?”: socket à escuta sem dono conhecido é candidato a investigação, e CLOSE_WAIT acumulados apontam para aplicações que não fecham ligações.
Um limite do -i que a FAQ lembra: ligações em TIME_WAIT ou FIN_WAIT nem sempre têm processo por trás — o socket já não pertence a ninguém — e o lsof não as vê. Também por isso o pedido “quem segura a porta 8080” pode chegar disfarçado: o “address already in use” nem sempre nasce de um processo vivo — sockets em TIME_WAIT também o causam, e aí o ss -tanp mostra o estado que o lsof esconde.
5. O que este processo tem aberto: -p, -c e -g
A partir do PID, o -p lista tudo o que o processo detém:
lsof -p 1234
lsof -p 1234,5678
Quando se conhece o nome do comando em vez do PID, o -c evita procurar o PID primeiro — o manual usa o sendmail como exemplo:
lsof -c nginx
lsof -c sshd
- O
-ccasa pelo começo do nome do comando. Vários-csomam-se (OR). Aceita também expressão regular entre barras:lsof -c /^..o.$/i. - O
-ufiltra por utilizador e aceita a negação^:lsof -u www-datasão os ficheiros do utilizador. Elsof -u^rootexclui todos os processos do root — a negação aplica-se antes dos restantes critérios. - O
-gselecciona por grupo de processos e, sem argumento, acrescenta a coluna PGID à saída. - Importante: sem o
-a, os critérios de selecção somam-se por OR.lsof -p 1234 -u postgreslista os ficheiros do PID 1234 mais os do utilizador postgres. Para a intersecção, é preciso-a:lsof -a -p 1234 -u postgres. Esta regra é a origem de muitos resultados “a mais” quando se combinam filtros.
6. Ficheiros apagados que continuam a gastar disco
O df acusa disco cheio, o du não encontra a culpa, e a explicação é um ficheiro apagado com rm enquanto um processo o mantinha aberto — tipicamente um log rodado pelo logrotate com um serviço antigo a escrever nele. O espaço só é libertado quando o último descritor fecha.
O lsof apanha o caso por dois caminhos. O +L1 lista os ficheiros abertos com link count zero — o estado exacto de um ficheiro desligado do sistema de ficheiros mas ainda aberto:
lsof +L1
lsof -a +L1 /var
Uma nota sobre o filtro por directório: o lsof -a +L1 /var só restringe aos apagados dessa árvore quando o /var é ponto de montagem próprio — caso contrário, o manual trata-o como um directório simples e a lista cobre o sistema de ficheiros todo.
No Linux, os caminhos de ficheiros apagados são reportados por omissão com o sufixo (deleted) no fim — pergunta da FAQ oficial do lsof:
sudo lsof | grep deleted
rsyslogd 812 syslog 7w REG 254,1 2147483648 521214 /var/log/syslog (deleted)
A recuperação passa pelo /proc: enquanto o descritor estiver aberto, o conteúdo continua acessível em /proc/PID/fd/N — o número é o da coluna FD, aqui o 7:
sudo ls -l /proc/812/fd/7
sudo cp /proc/812/fd/7 /var/log/syslog.recuperado
A cópia sai igual ao conteúdo que o processo vê. Duas notas: a cópia não é o mesmo inode — o serviço continua a escrever no ficheiro antigo, e sem reinício o espaço nunca se liberta. Com o descritor aberto em escrita, é possível truncar via /proc sem reiniciar, mas isso é medida de incidente, não rotina.
O tutorial oficial chama a este caso “Finding an Unlinked Open File” e usa exactamente o lsof +L1 para o encontrar.
7. Sockets Unix, NFS e o que o lsof conta como ficheiro
Uma socket UNIX é também um ficheiro aberto, e o -U lista essa família:
lsof -U
lsof -i -U
lsof -i -Ué o exemplo do manual para “todos os ficheiros de rede, Internet e domínio UNIX”.- O
-Nlista os ficheiros montados por NFS, do lado do cliente. Nota do manual: num servidor NFS, olsofnão mostra os ficheiros que os clientes têm abertos — só vê os processos da máquina onde corre. - A coluna TYPE distingue
unix,IPv4,IPv6,REG,DIR— é ela que diz se uma linha de/var/run/...é ficheiro regular ou socket. - A opção
-Eacrescenta os pontos de ligação (endpoints) de pipes e sockets UNIX do Linux — quem está do outro lado de um socket.
8. Quando o lsof trava: NFS inacessível, -b e -S
O lsof usa as chamadas stat(2), lstat(2) e readlink(2) para montar a tabela — e estas podem bloquear no kernel quando um NFS perde o servidor. A FAQ oficial dedica-lhe uma secção: cada ponto de montagem sem resposta custa quinze segundos por omissão, e um servidor com vários pontos NFS mortos parece congelado.
sudo lsof -S 5
sudo lsof -b -w
-S 5reduz o tempo de espera para cinco segundos por sistema de ficheiros.-bevita as chamadas que podem bloquear — a custo de informação em falta e de avisos, silenciáveis com-w(forma combinada:lsof -bw).- Serve para discos de um servidor NFS que caiu:
lsof -b /mnt/nfsainda lista os ficheiros abertos, desde que a tabela de montagens forneça o número de dispositivo alternativo. - Se a lentidão vier da resolução de nomes ou de portas, a receita da FAQ é
-ne-P— o mesmo par da secção 4.
9. Scripts: -t, exit code e o pipeline com wc
O -t imprime só os PIDs, sem cabeçalho — a forma de alimentar kill e xargs. O exemplo do manual:
lsof -t /lib/*/libssl.so.* | xargs -r kill -HUP
Em produção, o kill -HUP a processos que não tenham handler de SIGHUP mata a aplicação — o padrão do manual vale para serviços que recarregam com HUP, e para os outros o reinício de processo (com rollback) é o caminho seguro.
kill -HUP `lsof -t /var/log/app.log`
O exit code é o contrato para scripts: o lsof sai com 0 quando encontrou tudo o que lhe foi pedido e 1 quando alguma pesquisa falhou — com o -Q a ignorar os termos sem resultados. O manual mostra o padrão:
if lsof /u/abe/foo > /dev/null 2>&1; then
echo "ficheiro ainda em uso"
fi
Para contar linhas de saída — quantos ficheiros tem um processo aberto, quantas ligações um serviço mantém — o pipeline com wc -l é o atalho:
lsof -p 1234 | wc -l
lsof -iTCP:443 | wc -l
lsof -u www-data | wc -l
Contas a ter em conta: o cabeçalho conta como linha (subtrair 1, ou tail -n +2), e sem sudo um utilizador só vê os próprios ficheiros — a contagem de processos alheios sai truncada sem erro.
Uma nota que a FAQ sublinha: o lsof -p PID | wc -l não é o número de descritores do processo — a saída inclui cwd, rtd, txt e mem, que não ocupam descritores. Para contar descritores reais (o limite do ulimit), o caminho certo é ls /proc/PID/fd | wc -l.
Para contagens periódicas, o modo repeat -r N repete a listagem cada N segundos sem o custo de arranque de chamadas repetidas na shell.
10. Diagnóstico de segurança com o lsof
Para além do incêndio do dia, o lsof responde a duas perguntas de segurança que os inventários estáticos não cobrem:
sudo lsof -iTCP -sTCP:LISTEN -P -n
sudo lsof -u^root -a -i
- A primeira é o inventário de portas à escuta com processo associado — é a lista que se compara com a linha de base do servidor. Qualquer entrada nova, em interface inesperada ou sem dono conhecido, merece investigação.
- A segunda (negação +
-a) responde a “que ligações de rede existem fora dos processos do root” — o sítio onde um processo comprometido sob utilizador de serviço se esconde. - Um executável a correr de
/tmpou/dev/shmnão aparece pelo-i— o NAME dessa saída mostra endereços e portas, não o caminho do binário. O detector certo é o descritor de texto:sudo lsof -d txt | grep -E '/tmp|/dev/shm'(alternativa:ls -l /proc/*/exe). Encontrado o PID, olsof -a -i -p PIDmostra os sockets que ele mantém. - Compilado com
--enable-security, o lsof deixa cada utilizador listar só os próprios ficheiros — daí osudoem quase tudo. Olsof -hmostra se a instalação tem essa restrição.
Erros Comuns
| Sintoma | Causa provável | Correcção |
|---|---|---|
lsof -p 1234 -u postgres devolve demasiado |
Critérios somados por OR | -a: lsof -a -p 1234 -u postgres |
Porta aparece em ss mas não no lsof -i |
Sem root, o lsof não vê os ficheiros dos outros utilizadores | sudo lsof -i :PORTA |
O lsof parece congelado |
Ponto de montagem NFS com o servidor em baixo (15 s por montagem por omissão) | -S 5 ou -b -w; resolver a montagem a seguir |
Disco cheio, du não encontra nada |
Ficheiro apagado ainda aberto por um processo | sudo lsof +L1 e reiniciar o processo que o segura |
lsof +D / demora minutos |
O +D percorre a árvore toda com stat(2) a cada nó |
Usar o nome do sistema de ficheiros (lsof /) ou +d no directório de topo |
Contagem de wc -l errada |
Cabeçalho contado, ou linhas a faltar sem sudo | lsof ... | tail -n +2 | wc -l, sempre com o mesmo privilégio |
lsof -i lento |
Resolução de nomes DNS e de serviços em falta | -n -P (e lsof -h para confirmar os valores por omissão) |
umount: target is busy sem processo visível |
Ficheiro aberto em shell (cwd), socket ou processo com directório no disco | lsof /ponto/de/montagem e lsof +D /ponto/de/montagem |
Checklist
- [ ]
lsof -vresponde com a revisão instalada (4.95.0 no Debian 12, 4.99.4 no Debian 13) - [ ] Quem segura um ficheiro:
lsof /caminho/ficheiro(com sudo quando o ficheiro é de outro utilizador) - [ ] Portas:
lsof -nP -i :PORTApara uma porta,lsof -iTCP -sTCP:LISTENpara o inventário de escuta - [ ] Processo:
lsof -p PIDe, sem PID,lsof -c nome - [ ] Filtros combinados com
-a(o OR é o comportamento por omissão) - [ ] Ficheiros apagados:
sudo lsof +L1, recuperação por/proc/PID/fd/N - [ ] Directórios:
+dno topo,+Dsó em árvores pequenas (o manual avisa que pode ser lento) - [ ] NFS problemático:
-S 5ou-b -wantes de declarar o lsof bloqueado - [ ] Scripts:
-tpara PIDs akill/xargs, exit code 0/1 para decisões,-r Npara repetição - [ ] Inventário de segurança:
lsof -iTCP -sTCP:LISTEN -P -ncomparado com a baseline
Artigos Relacionados
- Dia 5: Processos e Jobs no Linux — ps, top, kill e Sinais — o que fazer com os PIDs que o lsof devolve: sinais, jobs e prioridades.
- Dia 28: Performance Tuning no Linux — CPU, Memória, I/O e perf — o passo seguinte quando o lsof mostra quem abriu e é preciso medir quanto custa.
- Ferramentas avançadas de diagnostico linux — o mapa das ferramentas de diagnóstico, com o lsof no sítio certo entre strace, perf e afins.
- journalctl: Diagnóstico de Serviços Linux do journal ao Root Cause — depois de descobrir o processo pelo lsof, o journal conta o que ele fez.
- Monit: Monitorização e Reparação Automática de Serviços Linux — a vigilância contínua que reinicia o serviço antes de o incidente de disco cheio acontecer.
Fontes Oficiais
- Man page lsof(8) (man7.org) — a referência completa da sintaxe: gramática do
-i,-p,-u,-t,+D,+L1, colunas FD/TYPE e o aviso de desempenho do+D. - Documentação oficial do lsof (lsof.readthedocs.io) — o tutorial oficial dos mantenedores: casos de ficheiro aberto, unlinked files, umount, sockets e exit code.
- Repositório lsof-org/lsof no GitHub — o código-fonte mantido (série 4.99.x), com as release notes de cada versão e as opções novas:
-H(tamanhos legíveis, a partir da 4.98) e-J/-j(saída JSON, a partir da 4.99.7. O-Qjá vem da 4.95.0. - FAQ oficial (docs/faq.md) — as respostas aos casos
(deleted), bloqueios com NFS,-S/-b/-we a lentidão com-n/-P. - Pacote lsof em Debian (bookworm/trixie) — versões por distribuição: 4.95.0 no Debian 12, 4.99.4 no Debian 13.
- Pacote lsof no Ubuntu — 4.95.0 no 24.04 LTS, série 4.99.4 a partir das versões seguintes.