As Utilidades Do Comando lsof

Introdução

Dos vários comandos do Linux, há aqueles que requerem um pouco de atenção, e um deles é o comando lsof. Esse comando simplesmente mostra arquivos abertos no sistema, porém, como praticamente tudo no Linux é um arquivo, esse comando se mostra muito útil na depuração de problemas.

Esse post mostrará alguns usos do lsof e como também alguns exemplos mais elaborados. A leitura das referências é indispensável para maiores informações.

O lsof

Esse comando basicamente mostra os arquivos abertos no sistema. Entenda-se por arquivos abertos, os arquivos regulares, os diretórios, os links, arquivos de blocos e caractere, bibliotecas compartilhadas, pipes, named pipes (FIFO), sockets de Internet, sockets do Unix, e muitos outros. Além disso, o lsof associa a cada um desses arquivos outras informações úteis, como o processo que abriu tal arquivo, o dono do processo, arquivo descritor, etc.

Visualizando todos arquivos abertos

Quando invocado sem opções, o lsof mostra todos os arquivos abertos no sistema. Como esse comando acessa informações do kernel, sempre que possível o execute como root (#) para um resultado mais completo e detalhado.

Saída lsof

Saída lsof

A opção -n impede resolução de nomes para sockets de Internet, tornando o processamento do comando muito mais rápido. Bem, o lsof nos retorna informações na forma de colunas. As quatro primeiras colunas nos diz o nome do processo, o seu PID, em seguida o TID (thread ID) e o nome do dono, respectivamente. FD, Type, Device, SIZE/OFF e Node já dizem a respeito do arquivo. O Type é o tipo do arquivo, como DIR para diretório e REG para arquivos regulares. Device é onde o arquivo está e SIZE/OFF mostra o tamanho do arquivo e em alguns sistemas, o offset atual onde será realizada uma operação de I/O. A coluna Node é o número do inode do arquivo.

Em se tratanto de arquivos, as colunas FD e Type são as mais importantes, pois detalham melhor o arquivo aberto. A coluna FD representa a visão que o processo tem do arquivo e a Type, a forma do arquivo.

Vemos que o processo de PID 22299 vê o diretório /home/daemonio como CWD, ou seja, o diretório atual do processo. O valor txt em FD indica um executável em si, referenciando a seção texto dos arquivos binários. O valor mem é o tipo dos arquivos que estão mapeados na memória, como os arquivos de bibliotecas. Quando FD assume um valor numérico, esse valor nada mais é que arquivo descritor de arquivo retornado por alguma chamada do sistema, como open() e socket(). Além desse descritor, a coluna FD também no diz as permissões sobre esse fd. Um ‘u’ indica que o descritor foi aberto tanto para leitura (‘r’) quanto para escrita (‘w’).

Exemplos de uso

A seguir listarei alguns exemplos de uso do comando e sempre que possível detalharei as opções usadas.

1) Verificar qual processo abriu determinado arquivo

Você pode passar o nome de um arquivo para o lsof para descobrir quais processos manipulam tal arquivo:

Saída lsof - arquivo

Saída lsof – arquivo

Um exemplo útil para atacantes é descobrir servidores de logs de um sistema:

# lsof /dev/log

2) Descobrindo qual processo está travando um ponto de montagem

Você já tentou desmontar uma partição e se deparou que não era possível, pois ela estava ocupada? Com o lsof você consegue descobrir qual processo está impedindo o desmontamento:

# lsof /media/4CB0-7B91
COMMAND   PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
bash    23040 daemonio  cwd    DIR   8,16     8192    1 /media/4CB0-7B91

Para desmontar com sucesso esta partição, os processos listados devem ser finalizados. Esse exemplo nos mostra como o diretório atual de um processo é importante, porque ele pode impedir um sistema de arquivos de ser desmontado. É por isso que processos que rodam em background (os daemons) sempre dão chdir() para o diretório root ou um diretório montando em / para que eles não travem o desmontamento de algum sistema de arquivo do usuário.[1]

3) Arquivos abertos por determinados processos

A opção -c filtra pelo nome de um processo:

# lsof -c lsof

faz o mesmo que o comando seguir, porém de uma forma muito mais rápida:

# lsof | grep lsof  # prefira o uso da opção -c por ser mais rápido

A saída mostra todos os arquivos abertos pelo processo lsof. O nome do processo não precisa ser completo, bastando apenas indicar o início do nome do mesmo.

Se vários processos são desejados, a opção -c pode ser usada mais de uma vez:

# lsof -c bash -c zsh

nesse caso, a opção trabalha como um OU: tantos os arquivos do processo bash e do zsh foram mostrados. Para simular um AND, use a opção -a, como veremos mais a frente.

5) Arquivos abertos por um usuário

A opção -u filtra os arquivos abertos por determinado usuário:

# lsof -u hacker

O lsof é bastante livre e aceita o uso das opções ao mesmo tempo:

# lsof -u hacker -c bash

A saída é todos os arquivos do usuário hacker e do processo bash. Para mostrar os arquivos que sejam do hacker E do processo em questão, use a opção -a, que realiza um AND na entrada:

# lsof -a -u hacker -c bash

6) Negando padrões

As opções -u e -c, e muitas outras, podem receber um padrão negado, isto é, podemos obter os arquivos que não sejam de determinados usuários e processos.

# lsof -u ^daemonio

Mostra os arquivos de todos os usuários, exceto os do usuário daemonio.

Com a opção -p, filtramos os arquivos abertos por um processo de pid PID:

# lsof -p 1  # processo init

Vários PIDs podem ser separados por vírgula:

# lsof -p 1,4458,3396

e também negados:

# lsof -p ^1  # todos processos, exceto o init

lsof e informações de rede

Os usos mais úteis do lsof são aqueles voltados a rede. Com esse comando, podemos obter qual processo roda em determinada porta, quais processos abriram conexões TCP, e etc.

Os exemplos a seguir sempre virão com a opção -n que impede a resolução de nomes e portas, tornando o processamento do comando muito mais rápido.

7) Qual processo usa determinada porta

A opção -i é muito flexível, pois aceita várias formatos de opção. Ela, sem argumentos, retorna os sockets abertos pelos processos do sistema. Seu uso é:

# ls -i [46][protocolo][@hostname ou hostaddr][:serviço ou porta]

Lembrando que tudo entre [] é opcional e pode ser ocultado. O 4 e 6 são referentes a versão dos protocolos (IPv4 ou IPv6). protocolo pode ser tanto TCP e UDP e o restante do parâmetro se refere a um host e a um serviço.

Sabendo disso, para mostrar os processos que usam a porta 80, basta digitar:

# lsof -n -i :80

A porta pode ser um número ou algum serviço (veja /etc/services), ou seja, tanto faz passar 25 ou smtp que o efeito é o mesmo.

Observe que os processos retornados são aqueles que utilizam a porta tanto como fonte quanto destino. Para a porta 80, a saída será composta de navegadores web abertos e também do servidor web.

Uma peculiaridade do lsof é que algumas opções podem receber intervalos, e a -i é uma delas:

# lsof -n -i :21-80

Lista sockets que se relacionam com as portas no intervalo [20, 80].

E refinando ainda mais a saída, podemos encontrar portas esperando por conexões (em estado LISTEN):

# lsof -n -i TCP:80 | grep LISTEN
COMMAND     PID     USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
nc        24538     root    3u  IPv4 4092794      0t0  TCP *:http (LISTEN)

8) Usuários com sockets abertos

Vale ressaltar que as opções vistas até então podem ser usadas conjuntamente. Se a opção adicional -a for usada, o comportamento é semelhante a um AND:

# lsof -u daemonio -i

Lista sockets abertos (-i) pelo usuário daemonio (-u)

9) Recuperando arquivos deletados

Se de alguma maneira um arquivo foi deletado e se um processo o continua usando, então esse arquivo pode ser recuperado. Aqui no blog já mostrei como utilizar desse fato para recuperar vídeos flash de sites como youtube, vimeo, etc. Veja mais detalhes em [6].

Aqui usarei arquivos flash como exemplo, porque o plugin flash automaticamente deleta o arquivo depois de aberto. A primeira coisa a ser feita é obter o descritor do arquivo aberto:

# lsof -n | grep deleted
chrome    16191       daemonio   34u      REG        8,3      24283    1191801 /tmp/FlashXXHdHTgl (deleted)

Tendo O FD, o PID do processo e contando com a ajuda do diretório /proc, podemos, por exemplo, copiar esse arquivo deletado para outro diretório:

$ cp /proc/19167/fd/34 ~/videos/meu_video.flv

Em [7] vemos que essa característica também é usada por hackers. Arquivos deletados não são visíveis quando comandos como ls e find são usados, dificultando a vida de administradores de sistemas a procura de possíveis pistas de invasão.

Resumo das opções

As opções vistas aqui foram as -c, -u, -p, -i e -a. A tabela seguinte resume o uso dessas opções.

+-------+-----------------------------------------------------+
|Opção  |                      Descrição                      |
+-------+-----------------------------------------------------+
|  -c   |           Arquivos abertos por um comando.          |
+-------+-----------------------------------------------------+
|  -u   |            Arquivos abertos de um usuário.          |
+-------+-----------------------------------------------------+
|  -p   |          Arquivos abertos pelo processo PID.        |
+-------+-----------------------------------------------------+
|  -i   | Análise de sockets. Aceita protocolo, host e porta. |
+-------+-----------------------------------------------------+
|  -a   |              Faz um AND com as opções.              |
+-------+-----------------------------------------------------+

O lsof é mais do que isso, e para uma leitura mais detalhada, consulte a man page do programa:

$ man lsof

Referências

[1] Finding open files with lsof by Sean A. Walberg (Acessado em: Agosto/2012)
http://www.ibm.com/developerworks/aix/library/au-lsof.html

[2] A Unix Utility You Should Know About: lsof by Peteris Krumin (Acessado em: Agosto/2012)
http://www.catonmat.net/blog/unix-utilities-lsof/

[3] lsof by daenielmiessler (Acessado em: Agosto/2012)
http://danielmiessler.com/study/lsof/

[4] How to use the lsof command by Jonathan Peck (Acessado em: Agosto/2012)
http://www.novell.com/coolsolutions/tip/18078.html

[5] Recover Deleted Linux Files With lsof by Juliet Kemp (Acessado em: Agosto/2012)
http://www.linuxplanet.com/linuxplanet/tips/6767/1

[6] Para Onde Foram Os Arquivos Flash Do /tmp by Daemonio (Acessado em: Agosto/2012)
https://daemoniolabs.wordpress.com/2011/07/23/para-onde-foram-os-arquivos-flash-do-tmp/

[7] Recovering files from /Proc by Bri Hatch. (Acessado em: Agosto/2012)
http://www.hackinglinuxexposed.com/articles/20020507.html

Deixe um comentário