Linux: El comando lsof

Lsof es una potente herramienta disponible en la shell de Linux que lista los ficheros abiertos en el sistema. Partiendo de esta base, podemos conocer rápidamente que ficheros mantiene abiertos un determinado proceso (PID) o usuario e información adicional como el puerto utilizado por dichos servicios/ficheros, sockets en uso, etc.

Lanzando el comando lsof sin ningún parámetro listará todos los ficheros abiertos en la máquina en ese momento, no es recomendable ya que como imaginaréis saldrá una cantidad enorme.

Algunos de los ejemplos de uso más comunes son los siguientes:

Listar los ficheros abiertos de un determinado PID

# lsof -p PID

Ejemplo, vamos a listar los ficheros abiertos de un PID perteneciente a apache, también veremos los sockets y puertos en los que escucha el proceso:

# lsof -p 15826
COMMAND   PID   USER   FD   TYPE     DEVICE    SIZE       NODE NAME
httpd   15826 apache  cwd    DIR        8,2    4096          2 /
httpd   15826 apache  rtd    DIR        8,2    4096          2 /
httpd   15826 apache  txt    REG        8,2  312340    6764473 /usr/sbin/httpd
httpd   15826 apache  DEL    REG        8,2            6761188 /usr/lib/libldap-2.3.so.0.2.15.#prelink#.MN10ei
httpd   15826 apache  mem    REG        8,2 1009712    8585265 /lib/libdb-4.3.so
httpd   15826 apache  mem    REG        8,2  125744    8589007 /lib/libpthread-2.5.so
httpd   15826 apache  mem    REG        8,2   15704    8585423 /lib/libuuid.so.1.2
httpd   15826 apache  mem    REG        8,2            6764446 /usr/lib/libpq.so.4.1 (path inode=6765089)
httpd   15826 apache  mem    REG        8,2  101404    8589003 /lib/libnsl-2.5.so
httpd   15826 apache  mem    REG        8,2  133056    8589019 /lib/libexpat.so.0.5.0
httpd   15826 apache  mem    REG        8,2  190712    6764712 /usr/lib/libgssapi_krb5.so.2.2
httpd   15826 apache  mem    REG        8,2   16428    8589004 /lib/libdl-2.5.so
httpd   15826 apache  mem    REG        8,2  281116    8585251 /lib/libssl.so.0.9.8b
httpd   15826 apache  mem    REG        8,2   75028    6751429 /usr/lib/libz.so.1.2.3
httpd   15826 apache  mem    REG        8,2   33648    6764709 /usr/lib/libkrb5support.so.0.1
httpd   15826 apache  mem    REG        8,2    7880    8585403 /lib/libkeyutils-1.2.so
httpd   15826 apache  mem    REG        8,2    5500    6981504 /usr/lib/httpd/modules/mod_authn_file.so
httpd   15826 apache  mem    REG        8,2 1597968    8588999 /lib/libc-2.5.so
[...]

Como veis muestra información de gran utilidad  como el servicio/comando al que pertenece el proceso (COMMAND), el PID, usuario que lo está ejecutando (USER), el descriptor de archivo (FD), tipo de nodo asociado con el fichero (TYPE), número de dispositivo (DEVICE), el tamaño del fichero y el nombre/ruta al mismo.

Echad un vistazo a las páginas man (man lsof) para ver una descripción extendida de cada columna.

Listar ficheros abiertos en un dispositivo o partición:

Para evitar el típico fallo de no poder desmontarlo porque la partición o el dispositivo está en uso:

# lsof /particion

Listar ficheros abiertos de un determinado usuario:

# lsof -u alex

COMMAND     PID USER   FD      TYPE     DEVICE      SIZE    NODE NAME
gnome-key  2862 alex  cwd       DIR        8,3      4096  107912 /var/lib/gdm
gnome-key  2862 alex  rtd       DIR        8,3      4096       2 /
gnome-key  2862 alex  txt       REG        8,3    588132    6979 /usr/bin/gnome-keyring-daemon
gnome-key  2862 alex  mem       REG        8,3     42974   76307 /usr/share/locale-langpack/es/LC_MESSAGES/glib20.mo
gnome-key  2862 alex  mem       REG        8,3    133662   76393 /usr/share/locale-langpack/es/LC_MESSAGES/libc.mo
gnome-key  2862 alex  mem       REG        8,3     42504    6194 /lib/tls/i686/cmov/libnss_files-2.9.so
gnome-key  2862 alex  mem       REG        8,3     38444    6198 /lib/tls/i686/cmov/libnss_nis-2.9.so
gnome-key  2862 alex  mem       REG        8,3     87804    6188 /lib/tls/i686/cmov/libnsl-2.9.so
gnome-key  2862 alex  mem       REG        8,3     30436    6190 /lib/tls/i686/cmov/libnss_compat-2.9.so
gnome-key  2862 alex  mem       REG        8,3     30765   76316 /usr/share/locale-langpack/es/LC_MESSAGES/gnome-keyring.mo
gnome-key  2862 alex  mem       REG        8,3    256316   13609 /usr/lib/locale/es_ES.utf8/LC_CTYPE
gnome-key  2862 alex  mem       REG        8,3        54   13614 /usr/lib/locale/es_ES.utf8/LC_NUMERIC
[...]

Ver actividad de red en tiempo real

Pese a que hay otras herramientas más indicadas para este tipo de tareas (véase iptraf, iftop o tcpdump), lsof permite visualizar los puertos TCP y UDP en escucha así como las conexiones activas en el sistema. Para ello utilizamos el parámetro «-i»

# lsof -i
COMMAND    PID       USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
rsyslogd   917     syslog    3u  IPv4   7084      0t0  UDP *:syslog 
rsyslogd   917     syslog    4u  IPv6   7085      0t0  UDP *:syslog 
avahi-dae  942      avahi   13u  IPv4   8851      0t0  UDP *:mdns 
avahi-dae  942      avahi   14u  IPv6   8852      0t0  UDP *:mdns 
avahi-dae  942      avahi   15u  IPv4   8853      0t0  UDP *:47513 
avahi-dae  942      avahi   16u  IPv6   8854      0t0  UDP *:52390 
iked.real 1199       root   15u  IPv4   8967      0t0  UDP *:isakmp 
iked.real 1199       root   16u  IPv4   8968      0t0  UDP *:4500 
cupsd     1379       root    5u  IPv6  10596      0t0  TCP ip6-localhost:ipp (LISTEN)
cupsd     1379       root    6u  IPv4  10597      0t0  TCP localhost:ipp (LISTEN)
vpnagentd 1572       root   12u  IPv4  10026      0t0  TCP localhost:29754 (LISTEN)
dhclient  1672       root    6u  IPv4  10193      0t0  UDP *:bootpc 
teamviewe 1681       root   14u  IPv4  11369      0t0  TCP localhost:5939 (LISTEN)
firefox   1964 	foo    65u  IPv4 250845      0t0  TCP www.test.com:54980->kix01s04-in-f15.1e100.net:https (CLOSE_WAIT)

Si no queremos ver la actividad en tiempo real sino una foto del momento en el que ejecutamos el comando, los parámetros a especificar son:

# lsof -P -i -n

Comprobar servicios/puertos que están escuchando

lsof -i -nP
COMMAND     PID    USER   FD   TYPE     DEVICE SIZE NODE NAME
portmap    2139     rpc    3u  IPv4       5220       UDP *:111
portmap    2139     rpc    4u  IPv4       5221       TCP *:111 (LISTEN)
rpc.statd  2164 rpcuser    3u  IPv4       5285       UDP *:647
rpc.statd  2164 rpcuser    6u  IPv4       5264       UDP *:644
rpc.statd  2164 rpcuser    7u  IPv4       5297       TCP *:650 (LISTEN)
sendmail   2437    root    4u  IPv4 1484615119       TCP 127.0.0.1:25 (LISTEN)
mysqld     2753   mysql   10u  IPv4  615583079       TCP *:3306 (LISTEN)
httpd      3063    root    3u  IPv6  583456545       TCP *:80 (LISTEN)
httpd      3063    root    5u  IPv6  583456550       TCP *:443 (LISTEN)

Ver archivos abiertos por un proceso o programa concreto

Con el parámetro «-c» podemos visualizar los archivos abiertos por un proceso en ejecución así como los puertos en los que está escuchando y sus conexiones establecidas. El siguiente ejemplo muestra los archivos y conexiones del proceso cupsd:

# lsof -c cupsd
COMMAND  PID USER   FD   TYPE             DEVICE SIZE/OFF   NODE NAME
cupsd   1379 root  cwd    DIR                8,5     4096      2 /
cupsd   1379 root  rtd    DIR                8,5     4096      2 /
cupsd   1379 root  txt    REG                8,5   436656 268733 /usr/sbin/cupsd
cupsd   1379 root  mem    REG                8,5    51728   4775 /lib/x86_64-linux-gnu/libnss_files-2.13.so
cupsd   1379 root  mem    REG                8,5    47680   4758 /lib/x86_64-linux-gnu/libnss_nis-2.13.so
cupsd   1379 root  mem    REG                8,5    35712   4774 /lib/x86_64-linux-gnu/libnss_compat-2.13.so
cupsd   1379 root  mem    REG                8,5    14280  59509 /lib/x86_64-linux-gnu/libgpg-error.so.0.8.0
cupsd   1379 root  mem    REG                8,5    10160  59511 /lib/x86_64-linux-gnu/libkeyutils.so.1.3
cupsd   1379 root  mem    REG                8,5    31104 264844 /usr/lib/x86_64-linux-gnu/libkrb5support.so
cupsd   1379 root    5u  IPv6              10596      0t0    TCP ip6-localhost:ipp (LISTEN)
cupsd   1379 root    6u  IPv4              10597      0t0    TCP localhost:ipp (LISTEN)

[...]

Ver archivos en uso por un usuario en un directorio/path concreto

El siguiente ejemplo muestra un listado de los archivos en uso dentro del filesytem /tmp por parte del usuario «foo»:

# lsof -u foo -a +D /tmp

COMMAND    PID       USER   FD   TYPE             DEVICE SIZE/OFF   NODE NAME
gnome-key 1872 foo    5u  unix 0xffff8801266909c0      0t0  11778 /tmp/keyring-Ed3q50/control
gnome-key 1872 foo    9u  unix 0xffff88012b929d40      0t0  14609 /tmp/keyring-Ed3q50/pkcs11
gnome-key 1872 foo   10u  unix 0xffff8801183f56c0      0t0  14638 /tmp/keyring-Ed3q50/ssh
ssh-agent 1920 foo    3u  unix 0xffff88011bfb2700      0t0  12569 /tmp/ssh-lFsqTbDh1891/agent.1891
xfce4-ses 1940 foo    8u  unix 0xffff88011bfb0d00      0t0  12592 /tmp/.ICE-unix/1940
[...]

Visualizar archivos abiertos de un directorio/path concreto

El parámetro «+D» seguido de un path muestra los archivos abiertos de esa ruta especificada. Por ejemplo, para mostrar los archivos abiertos y por quien en /etc:

# lsof +D /etc
COMMAND    PID       USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
avahi-dae  942      avahi  cwd    DIR    8,5     4096 53003 /etc/avahi
avahi-dae  942      avahi  rtd    DIR    8,5     4096 53003 /etc/avahi
Xorg      1074       root  cwd    DIR    8,5     4096 52995 /etc/X11
sh        1891 	foo   10r   REG    8,5     9892 55384 /etc/xdg/xfce4/xinitrc
applet.py 2026 	foo   12u   REG    8,5     1851  4437 /etc/passwd
soffice.b 3581 	foo   52r   REG    8,5     1851  4437 /etc/passwd
[...]

Esto son solo algunos ejemplos de lo útil que puede resultar este comando, os recomiendo trastear un poco con él y veréis como seguro le sacáis partido en muchas ocasiones. En algunos casos las mismas tareas se pueden realizar con otros comandos de forma más óptima (netstat por ejemplo), aunque nunca viene mal conoer varias formas de ejecutar una misma tarea. Y recordad:

man lsof