¿Cómo puedo determinar qué proceso tiene un archivo abierto en Linux?

124

Me gustaría determinar qué proceso tiene la propiedad de un archivo de bloqueo. Los archivos de bloqueo son simplemente un archivo con un nombre específico que se ha creado.

Entonces, ¿cómo puedo determinar qué proceso tiene un archivo en particular abierto en Linux? Preferiblemente, un tipo de línea única o una solución de herramienta Linux particular sería óptima.

Danny
fuente

Respuestas:

55

También puedes usar fuserpara esto:

~> less .vimrc
# put in background
~> fuser .vimrc
.vimrc:              28135
~> ps 28135
  PID TTY      STAT   TIME COMMAND
28135 pts/36   T      0:00 less .vimrc
Nathan Fellman
fuente
esto fue genial, pero para usarlo en un script tuve que verificar la longitud de salida.
chovy
¿Qué quieres decir con la longitud de salida?
Nathan Fellman
if [ fusor "$ archivo" `]; entonces exit`
Chovy
1
El fusor tiene un comportamiento extraño con los códigos de salida. devuelve 1 código de salida con dos estados: A / algún error interno, archivo comprobado que no se encuentra, etc., B / ningún proceso abrió el archivo especificado. En la situación A / algún mensaje de error se imprime en su salida. Desafortunadamente, cuando el archivo está disponible y se abre por algo, la salida se genera pero con el código de salida 0. Sería mejor si el fusor saliera con tres códigos, no dos como actualmente. Isoft es un poco peor de resolver porque esto está trabajando más lentamente.
Znik
Este es esencialmente el mismo patrón que lssigue: devuelve el código de salida 2 si hay un error (por ejemplo, una opción no válida especificada) o un archivo no encontrado (y 0 si informa con éxito la información).
Scott
144

En la mayoría de los sistemas Linux lsof NAMEhace el trabajo:

fin@r2d2:~$ lsof /home/fin
COMMAND   PID USER   FD   TYPE DEVICE SIZE    NODE NAME
bash    21310  fin  cwd    DIR    8,1 4096 5054467 /home/fin
lsof    21320  fin  cwd    DIR    8,1 4096 5054467 /home/fin
lsof    21321  fin  cwd    DIR    8,1 4096 5054467 /home/fin
fin@r2d2:~$
aleta
fuente
44
¿Y si no tienes lsof?
JoseLSegura
3
@JoseLSegura: Supongo que eres lo suficientemente ingenioso para que la respuesta 'luego instalar lsof' sea inútil para ti. ¿Puedes explicar tu problema? Si no tiene root, es probable que no tenga privs para averiguar si otro usuario tiene el archivo abierto de todos modos.
Michael Scheper
esto no parece funcionar para archivos, solo para directorios
Jason
@ Jason: funciona para archivos, pero las cwdlíneas (que informan el uso como el directorio de trabajo actual de un proceso) solo informan directorios.
reinierpost
9

Tener un archivo abierto no es un bloqueo porque, si cada proceso tiene que verificar si el archivo está abierto primero y no proceder si lo está, o crearlo / abrirlo si no lo está, entonces dos procesos podrían verificar simultáneamente, ambos encontrarán que no está abierto, entonces ambos lo crean o lo abren.

Para usar un archivo como bloqueo, la operación de verificación y bloqueo debe ser una operación única e ininterrumpida. Puede lograr esto en un sistema de archivos Unix creando un archivo con modo de solo lectura y eliminándolo para desbloquearlo. Si el archivo existe (y es de solo lectura), la creación del archivo fallará, por lo que obtendrá la comprobación y el bloqueo en una sola operación atómica.

Si su proceso de bloqueo es un script de shell que se ejecutará como un demonio, puede obtener este efecto utilizando umaskuna configuración por proceso que establece los permisos con los que se crean nuevos archivos:

oldumask = $ (umask)
umask 222 # también crea archivos que no se pueden escribir para el propietario
si echo $$> / var / lock / foo
entonces
    : bloqueo exitoso
más
    : bloqueo fallido
fi
umask $ oldumask
Esto también escribe el proceso de propiedad 'PID en el archivo, que resuelve su otro problema: cat /var/lock/foo
En cuanto a la pregunta específica "¿Qué procesos tienen abierto este archivo?", Esto puede ser útil cuando desea desmontar un sistema de archivos pero no puede porque algún proceso tiene un archivo abierto en él. Si no tiene esos comandos disponibles, puede preguntar /proccomo root:

ls -l /proc/*/cwd | grep '/var/lock/foo$'

o, como usuario mortal:

ls -l /proc/*/cwd 2>/dev/null | grep '/var/lock/foo$'

martinwguy
fuente
el método 'ls -l' funciona para Linux pero parece no funcionar para CygWin: no hay información sobre el bloqueo de archivos allí. ¿No sabrías cómo resolverlo? Gracias.
Sopalajo de Arrierez
No, no crea un archivo de solo lectura para un bloqueo, porque cuando su aplicación se bloquee, el archivo seguirá allí. Obligar al usuario a aclarar la basura después de que su aplicación bloqueada sea mental.
polkovnikov.ph
6

Si desea saber qué descriptor de archivo de proceso exacto se vincula a su archivo sin lsofo fuser- busque a través de /proc:

$ find /proc -regex '\/proc\/[0-9]+\/fd\/.*' -type l -lname "*$1*" -printf "%p -> %l\n" 2> /dev/null

Reemplace $1con el nombre de archivo abierto que está buscando. Puede modificar el -printfpara lo que quiera ver, o canalizar egrep -o '[0-9]+' | head -1para usar con la información de ese proceso.ps -Fp <pid>

La respuesta de @fin es la mejor respuesta, obviamente, pero para responder el comentario de @ JoseLSegura , si esto no está disponible, la solución anterior fue mi respuesta.$ lsof <filename>

Scott
fuente
2

Descubrí que usar la respuesta aceptada no enumeraba los procesos que estaban usando mi directorio (ubuntu 14.04).

Al final, utilicé lsof (enumerar archivos abiertos) y agarré su salida para encontrar el proceso ofensivo:

lsof | egrep "<regexp-for-your-file>"
Eosis
fuente
Una forma más limpia y rápida para este uso lsofes su opción -R. por ejemplo: lsof -R [filename]
tron5