LSOF: List the Open Files
lsof is a small and interesting utility that is able of finding all the open files in our Linux system. We need to bear in mind that for Linux everything is a file - According to the man page:
An open file may be a regular file, a directory, a block special file, a character special file, an executing text reference, a library, a stream or a network file (Internet socket, NFS file or UNIX domain socket.) A specific file or all the files in a file system may be selected by path.A veces genera salida chunga en stderr (especialmente con temas de sistemas de ficheros overlay tipo docker, etc) - Es conveniente user lsof .... 2>/dev/null
Ficheros (regulares) abiertos
## Dice que proceso tiene abierto un fichero
lsof <file>
## Dice que procesos tienen abiertos ficheros en un directorio
lsof +D <dir>
Ficheros abiertos por usuario o proceso
# Archivos abiertos por usuario
lsof -u <usuario>
# Archivos abiertos por PID
lsof -p <pid>
La salida del comando, según la cabecera incluye los campos:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
- Command - El comamdo
- PID - El proceso
- USER - El usuario
- FD - File Descriptor - Que indica el descriptor de archivo y el modo en que el proceso lo tiene abierto.
0- stdin1- stdout2- stderrn- Número con el identificador de fichero abierto. Suele acompañarse por letras de permisosrlectura,wescritura,uupdate (lectura y escritura)
cwd- Current working directoryrtd- Root directory (el directorio raíz del proceso)txt- Archivo de texto, que generalmente es el ejecutable del programa.mem- Archivo mapeado en memoria (suelen ser librerías)REG- Archivo regularDIR- DirectorioCHR- Archivo especial de tipo caracter (p.e./dev/tty,/dev/pts/0)FIFO- Tubería o pipe para pasar datos entre procesos.UNIX- Socket de dominio UNIX localIPv4/IPv6- Conexión de red.DEL- Ficheros que no aparecen realmente en disco sino en sistemas de ficheros de memoria compartida /dev/shm (ej. brave) o ficheros en memoria (ficheros que sólo existen en memoria, no en disco) /memfd:pulseaudio
- DEVICE - Muestra los números de dispositivo separados por coma (mayor y menor) que sirve para identificar el dispositivo o partición en el que está
TYPE - Tipo de archivo que se está usando, que no tiene por qué ser algo en el disco:
# Ejemplo de ficheros CHR en mi shell zsh
❯ lsof -p 17062 2>/dev/null | grep CHR
zsh 17062 jicg 0u CHR 136,0 0t0 3 /dev/pts/0
zsh 17062 jicg 1u CHR 136,0 0t0 3 /dev/pts/0
zsh 17062 jicg 2u CHR 136,0 0t0 3 /dev/pts/0
zsh 17062 jicg 10u CHR 136,0 0t0 3 /dev/pts/0
# Siguiendo con el emplo anterior, tenemos 136,0 -- Justo tenemos ese
# dispositivo en /dev/pts y se corresponde con 0, 1, 2 (stdin, stdout
# y stderr).
❯ ls -l /dev/pts | grep 136
crw--w---- 1 jicg tty 136, 0 abr 16 10:30 0
crw--w---- 1 jicg tty 136, 1 abr 16 10:05 1
crw--w---- 1 jicg tty 136, 2 abr 16 10:30 2
# Otro que me sale mucho es 253,0 - Qué es la partición.
❯ ls -l /dev/ | grep 253
brw-rw---- 1 root disk 253, 0 abr 16 09:52 dm-0
- SIZE/OFF - Indicado el tamaño del fichero (regular) y el OFFSET del archivo en el programa.
NOTA - Aveces encontramos ficheros "borrados", es decir, un fichero que se ha borrado pero que el proceso que lo creó no lo ha cerrado -
tcpdump port 143 -w /tmp/f.pcap &
rm /tmp/f.pcap
# Ahora vemos el proceso y la marca de (deleted)
lsof -p 390635 2>/dev/null | grep deleted
tcpdump 390635 root 5w REG 0,36 0 10619 /tmp/f.pcap (deleted)
CONCEPTO FUNDAMENTAL DEL BORRADO DE FICHEROS
La gestión de almacenamiento de Linux - Como sabemos existe una separación entre el nombre del fichero (etiqueta que se ve en una carpeta) y el archivo en disco. En Linux sólo se borra el contenido del fichero cuando
- no hay ningún nombre (link) apuntando al fichero
- ningún proceso lo tiene abierto.
Archivo Zombie - Cuando un archivo se ha borrado y aún un proceso lo tiene abierto.
Esto tiene casos útiles:
- Actualización de librerías (.so) mientras un programa está en ejecución - Se borra el fichero de librería, pero como todavía está abierto por algunos programas, el archivo no se borra del disco.
- Seguridad y privacidad - Crear un fichero y luego borrarlo de forma que no se vea en el disco con el comando ls.
Putaditas:
- Si borras un archivo de log enorme por falta de disco, el espacio no se libera hasta que no se reinicia el servicio que lo mantiene abierto.
Temas de sockets / Conexiones de red
# Ver conexiones (o el puerto abierto)
# lsof -i [:puerto] ---
#
# -n (-n evita la resolución de nombres. Solo IP)
# -P (-P evita la conversión de números de puerto a nombres de puerto)
❯ sudo lsof -i :22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 964 root 6u IPv4 9690 0t0 TCP *:ssh (LISTEN)
sshd 964 root 7u IPv6 9692 0t0 TCP *:ssh (LISTEN)
❯ sudo lsof -Pi :22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 964 root 6u IPv4 9690 0t0 TCP *:22 (LISTEN)
sshd 964 root 7u IPv6 9692 0t0 TCP *:22 (LISTEN)
Parámetros para ver sockets
-i- Sockets UDP o TCP (puede aceptar parámetro :port)-U- Sockets Unix
El parámetro -ies realmente interesante -
# Listar todos los sockets TCP que estén en el estado LISTEN
sudo lsof -iTCP -sTCP:LISTEN -n -P
# Listar todos los sockets UDP (no tienen estado)
sudo lsof -iUDP -n -P
# Listar todos los sockets TCP y UDP
sudo lsof -i -n -P