Se a premissa de que tudo no Linux é um arquivo é verdadeira, então o sistema operacional gerencia muito mais do que apenas arquivos tradicionais em seu disco rígido. Este guia visa desmistificar o uso do comando `lsof` para expor a variedade de dispositivos e processos que são tratados internamente como arquivos.
No Linux, a Metáfora do Arquivo É Central
A afirmação de que “tudo no Linux é um arquivo” não é um mero clichê, mas sim uma representação da arquitetura do sistema. Um arquivo, em sua essência, é uma sequência de bytes. Quando um programa lê ou envia dados para uma impressora, esses dados se manifestam como um fluxo de bytes. De maneira análoga, quando gravamos dados, estamos alimentando um fluxo de bytes para um destino.
A filosofia do Linux estende essa abordagem a outros componentes do sistema, como teclados, conexões de rede, impressoras e processos comunicacionais. Esses dispositivos são capazes de gerar ou consumir fluxos de bytes, o que os torna elegíveis para serem tratados como arquivos em um nível de baixo nível.
Essa arquitetura simplificou drasticamente o desenvolvimento do sistema operacional Unix. Ao adotar um conjunto limitado de manipuladores, ferramentas e interfaces de programação (APIs), foi possível gerenciar uma vasta gama de recursos de maneira eficiente.
Os arquivos de dados e programas que residem em seu disco rígido são arquivos comuns do sistema. O comando `ls` é útil para listar e obter detalhes sobre eles.
Mas como podemos descobrir os outros processos e dispositivos que são tratados como arquivos? A resposta está no comando `lsof`, que lista todos os arquivos abertos no sistema, revelando o que está sendo tratado como um arquivo.
Explorando o Comando `lsof`
É importante notar que muitos processos e dispositivos que o `lsof` monitora pertencem ao usuário root ou foram iniciados por ele. Portanto, o comando `sudo` é essencial para executá-lo.
Como a lista de arquivos abertos tende a ser extensa, vamos canalizá-la para o comando `less` para facilitar a leitura:
sudo lsof | less
Usuários do GNOME podem se deparar com um aviso na janela do terminal antes da exibição da saída do `lsof`:
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs Output information may be incomplete.
O `lsof` procura processar todos os sistemas de arquivos montados. Essa mensagem de aviso é gerada ao encontrar um Sistema de Arquivos Virtual GNOME (GVFS). Este é um tipo específico de sistema de arquivos no espaço do usuário (FUSE), que atua como uma ponte entre o GNOME, suas APIs e o kernel. Apenas o proprietário que o montou (neste caso, o GNOME) pode acessar esse tipo de sistema de arquivos. Você pode ignorar este aviso sem prejuízo.
A saída do `lsof` é rica em informações. As colunas mais à esquerda exibem:
E as colunas mais à direita mostram:
Decifrando as Colunas do `lsof`
Nem todas as colunas são relevantes para todos os tipos de arquivos abertos, então não se preocupe com colunas que possam aparecer em branco.
Comando: O nome do comando associado ao processo que abriu o arquivo.
PID: O número de identificação do processo que abriu o arquivo.
TID: O número de identificação da tarefa (thread). Uma coluna em branco indica que não é uma tarefa, mas sim um processo.
Usuário: O ID do usuário ou nome de usuário ao qual o processo pertence, ou o ID do usuário ou login da pessoa que possui o diretório em `/proc` onde o `lsof` obtém informações sobre o processo.
FD: O descritor de arquivo. Mais detalhes sobre isso serão apresentados a seguir.
Tipo: O tipo de nó associado ao arquivo. Os tipos de nós também serão detalhados posteriormente.
Dispositivo: Os números dos dispositivos, separados por vírgulas, para arquivos especiais de caractere, bloco, arquivos regulares, diretórios ou arquivos NFS. Também pode exibir um endereço de referência do kernel ou o endereço base ou nome do dispositivo de um socket Linux AX.25.
Size/Off: O tamanho do arquivo ou o deslocamento do arquivo em bytes.
Nó: O número do nó de um arquivo local, o número do inode de um arquivo NFS no host do servidor, ou o tipo de protocolo da internet. Pode exibir “STR” para um fluxo, “IRQ” ou o número do inode de um socket Linux AX.25.
Nome: O nome do ponto de montagem e do sistema de arquivos onde o arquivo está localizado.
Entendendo a Coluna FD
O descritor de arquivo na coluna FD pode assumir diversos valores. Uma lista completa deles pode ser encontrada na página do manual do `lsof` em este link.
A entrada da coluna FD é composta por três partes: um descritor de arquivo, um caractere de modo e um caractere de bloqueio. Alguns descritores comuns são:
cwd: Diretório de trabalho atual.
err: Informação de erro do FD (veja a coluna NOME).
ltx: Texto da biblioteca compartilhada (código e dados).
m86: Arquivo mapeado do DOS Merge.
mem: Arquivo mapeado na memória.
mmap: Dispositivo mapeado na memória.
pd: Diretório pai.
rtd: Diretório raiz.
txt: Texto do programa (código e dados).
Um número que representa um descritor de arquivo.
O caractere de modo pode ser:
r: Acesso de leitura.
w: Acesso de gravação.
u: Acesso de leitura e gravação.
” “: Um espaço, indicando que o modo é desconhecido e não há caractere de bloqueio.
–: Modo desconhecido e existe um caractere de bloqueio.
E o caractere de bloqueio pode ser:
r: Bloqueio de leitura em parte do arquivo.
R: Bloqueio de leitura em todo o arquivo.
w: Bloqueio de escrita em parte do arquivo.
W: Bloqueio de escrita em todo o arquivo.
u: Bloqueio de leitura e escrita de qualquer comprimento.
U: Tipo de bloqueio desconhecido.
” “: Um espaço, indicando que não há bloqueio.
Analisando a Coluna TYPE
A coluna TYPE pode exibir mais de 70 entradas, mas algumas das mais comuns são:
REG: Arquivo normal do sistema de arquivos.
DIR: Diretório.
FIFO: Primeiro a entrar, primeiro a sair (fila).
CHR: Arquivo especial de caractere.
BLK: Arquivo especial de bloco.
INET: Socket de internet.
unix: Socket de domínio UNIX.
Encontrando Processos que Abriram um Arquivo
Para descobrir quais processos estão usando um arquivo específico, basta fornecer o nome do arquivo como um argumento para o `lsof`. Por exemplo, para ver os processos que acessaram o arquivo `kern.log`, utilize o seguinte comando:
sudo lsof /var/log/kern.log
O `lsof` exibirá o processo `rsyslogd`, iniciado pelo usuário `syslog`.
Listando Todos os Arquivos Abertos em um Diretório
Para verificar quais arquivos estão abertos em um determinado diretório e quais processos os abriram, passe o diretório para o `lsof` como um parâmetro, usando a opção `+D`.
Para verificar todos os arquivos abertos no diretório `/var/log/`, use:
sudo lsof +D /var/log/
O `lsof` listará todos os arquivos abertos nesse diretório.
Para inspecionar todos os arquivos abertos no diretório `/home`, use:
sudo lsof +D /home
A lista de arquivos abertos no diretório `/home` é exibida. Note que a lista é mais concisa devido à presença de descrições mais curtas em algumas colunas.
Filtrando por Processo
Para ver quais arquivos um processo específico abriu, use a opção `-c`. É possível usar múltiplos termos de busca simultaneamente.
sudo lsof -c ssh -c init
O `lsof` listará os arquivos abertos por qualquer um dos processos fornecidos.
Listando Arquivos Abertos por um Usuário
Para filtrar a listagem de arquivos por usuário, use a opção `-u`. O exemplo a seguir mostra os arquivos abertos por processos que pertencem à usuária “Mary”:
sudo lsof -u mary
Todos os arquivos listados foram abertos em nome da usuária Mary, incluindo arquivos abertos pelo ambiente de trabalho e como resultado do login de Mary.
Excluindo Arquivos Abertos por um Usuário
Para excluir arquivos abertos por um usuário específico, use o operador `^`. Isso facilita encontrar as informações relevantes. Utilize a opção `-u` e adicione `^` antes do nome do usuário.
sudo lsof +D /home -u ^mary
A listagem do diretório `/home` exclui todos os arquivos abertos pela usuária Mary.
Listando Arquivos Abertos por um Processo
Para listar os arquivos abertos por um processo com um ID específico, utilize a opção `-p`:
sudo lsof -p 4610
Todos os arquivos abertos pelo processo com o ID fornecido serão exibidos.
Listando IDs de Processo que Abriram um Arquivo
Para visualizar apenas os IDs de processo que abriram um arquivo, use a opção `-t`:
sudo lsof -t /usr/share/mime/mime.cache
Apenas os IDs de processo serão exibidos em uma lista simples.
Pesquisas com Operadores AND e OR
Vamos listar os arquivos abertos pela usuária Mary relacionados a processos SSH. Podemos usar múltiplos termos de busca, então a princípio, parece fácil:
sudo lsof -u mary -c ssh
Ao analisar a saída do `lsof`, notamos entradas que foram iniciadas pelo usuário root.
Isso não era o esperado. O que aconteceu?
Quando múltiplos termos de busca são usados, o `lsof` retorna arquivos que correspondem ao primeiro *ou* ao segundo termo de busca, ou seja, realiza uma pesquisa “OR”.
Para que o `lsof` execute uma pesquisa “AND”, use a opção `-a`. Isso significa que apenas os arquivos que correspondem a *todos* os termos de busca serão listados.
Vamos tentar novamente usando a opção `-a`:
sudo lsof -u mary -c ssh -a
Agora, todos os arquivos listados foram abertos por ou em nome de Mary e estão associados ao processo SSH.
Atualizando a Saída Automaticamente
Para que o `lsof` execute em modo de repetição, use as opções `+r` ou `-r`, juntamente com o número de segundos que deseja que o `lsof` espere antes de atualizar a tela.
O `lsof` exibirá os resultados normalmente e adicionará uma linha tracejada na parte inferior da tela, esperando o número de segundos especificado para atualizar a exibição.
Com a opção `-r`, a atualização continuará até que você pressione Ctrl+C. Com a opção `+r`, continuará até não haver resultados a exibir ou você pressionar Ctrl+C.
sudo lsof -u mary -c ssh -a -r5
A linha tracejada na parte inferior separa cada nova exibição de dados.
Exibindo Arquivos Associados a Conexões de Internet
A opção `-i` permite que você visualize arquivos abertos por processos ligados a conexões de rede e internet.
lsof -i
Todos os arquivos abertos por conexões de rede e internet serão mostrados.
Exibindo Arquivos Associados a Conexões de Internet por ID de Processo
Para ver arquivos abertos por conexões de internet associadas a um ID de processo específico, use as opções `-p` e `-a`.
O exemplo a seguir procura por arquivos abertos por uma ligação à Internet ou rede, por um processo com ID 606.
sudo lsof -i -a -p 606
Todos os arquivos abertos pelo processo ID 606, relacionados a conexões de internet ou rede, serão exibidos.
Exibindo Arquivos Associados a Conexões e Comandos da Internet
Podemos usar a opção `-c` para procurar arquivos abertos por processos específicos. Para encontrar arquivos abertos por conexões de internet ou rede associadas ao processo `ssh`, use:
lsof -i -a -c ssh
Todos os arquivos abertos devido aos processos `ssh` serão listados.
Exibindo Arquivos Associados a Conexões e Portas da Internet
O `lsof` pode reportar arquivos abertos por conexões de internet ou rede em uma porta específica, usando o caractere `:` seguido do número da porta.
O exemplo a seguir pede ao `lsof` que liste os arquivos abertos por conexões de rede ou internet que usam a porta 22.
lsof -i :22
Todos os arquivos listados foram abertos por processos associados à porta 22 (a porta padrão para conexões SSH).
Exibindo Arquivos Associados a Conexões e Protocolos de Internet
O `lsof` também pode mostrar arquivos abertos por processos associados a conexões de rede e internet que usam um protocolo específico (TCP, UDP ou SMTP). O exemplo a seguir mostra o uso do protocolo TCP.
sudo lsof -i tcp
Os únicos arquivos listados serão aqueles abertos por processos que usam o protocolo TCP.
Este É Apenas o Começo
Este guia abordou alguns casos de uso comuns para o comando `lsof`. No entanto, o `lsof` é capaz de muito mais. A página do manual do `lsof` possui mais de 2800 linhas, o que evidencia sua complexidade e versatilidade.
O comando `lsof` oferece meios para investigar as profundezas dos arquivos abertos e pseudo-arquivos no Linux. Este guia fornece um ponto de partida. O atlas completo está disponível na página do manual.