Comment puis-je déterminer quel processus a un fichier ouvert sous Linux?

124

Je voudrais déterminer quel processus a la propriété d'un fichier de verrouillage. Les fichiers de verrouillage sont simplement un fichier avec un nom spécifique qui a été créé.

Alors, comment puis-je déterminer quel processus a un fichier particulier ouvert sous Linux? De préférence, un type à une couche ou une solution particulière d’outil Linux serait optimal.

Danny
la source

Réponses:

55

Vous pouvez également utiliser fuserpour cela:

~> 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
la source
c'était génial, mais pour l'utiliser dans un script, je devais vérifier la longueur de la sortie.
Chovy
que voulez-vous dire par la longueur de sortie?
Nathan Fellman
if [ fuser "$ file" `]; puis sortie »
chovy
1
Le fuser a un comportement étrange avec les codes de sortie. il retourne 1 code de sortie avec deux états: A / une erreur interne, un fichier vérifié non trouvé, etc., le processus B / no a ouvert le fichier spécifié. Dans la situation A / un message d'erreur est imprimé sur sa sortie. Malheureusement, lorsque le fichier est disponible et ouvert par quelque chose, la sortie est générée mais avec le code de sortie 0. Il serait préférable que le fuser quitte avec trois codes, et non deux comme actuellement. La résolution de lsoft est un peu pire car elle fonctionne plus lentement.
Znik
Il s’agit essentiellement du même schéma qui lssuit: il renvoie le code de sortie 2 en cas d’erreur (par exemple, une option non valide spécifiée) ou un fichier introuvable (et 0 si le signalement est correct).
Scott
144

Sur la plupart des systèmes Linux lsof NAMEfait le travail:

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:~$
ailette
la source
4
Et si vous n'avez pas lsof?
JoseLSegura
3
@JoseLSegura: Je suppose que vous êtes assez débrouillard pour que la réponse 'then install lsof' soit inutile pour vous. Pouvez-vous élaborer sur votre problème? Si vous n'avez pas root, vous n'avez probablement pas de privilèges pour savoir si un autre utilisateur ouvre le fichier de toute façon.
Michael Scheper
cela ne semble pas fonctionner pour les fichiers, mais seulement pour les répertoires
Jason
@Jason: cela fonctionne pour les fichiers, mais les cwdlignes (qui utilisent rapport en tant que répertoire de travail actuel d'un processus) ne signalent que les répertoires.
reinierpost
9

Avoir un fichier ouvert n’est pas un verrou, car si chaque processus doit vérifier si le fichier est ouvert en premier et ne pas continuer s’il est ouvert ou le créer / l’ouvrir s’il ne l’est pas, alors deux processus pourraient très bien vérifier simultanément, les deux qu'il ne soit pas ouvert, alors les deux le créent ou l'ouvrent.

Pour utiliser un fichier en tant que verrou, l’opération d’archivage doit être une opération unique et ininterrompue. Vous pouvez y parvenir dans un système de fichiers Unix en créant un fichier en mode lecture seule et en le supprimant pour le déverrouiller. Si le fichier existe (et est en lecture seule), la création du fichier échouera. Vous obtiendrez ainsi check-and-lock en une seule opération atomique.

Si votre processus de verrouillage est un script shell qui s'exécutera en tant que démon, vous pouvez obtenir cet effet en utilisant umaskun paramètre par processus qui définit les autorisations avec lesquelles les nouveaux fichiers sont créés:

oldumask = $ (umask)
umask 222 # crée également des fichiers impossibles à écrire par le propriétaire
si echo $$> / var / lock / foo
ensuite
    : verrouillage réussi
autre
    : le verrouillage a échoué
Fi
umask $ oldumask
Ceci écrit également le PID du processus propriétaire dans le fichier, ce qui résout votre autre problème: cat /var/lock/foo
En ce qui concerne la question spécifique "Quels processus ont ce fichier ouvert?", Cela peut être utile lorsque vous souhaitez démonter un système de fichiers mais que vous ne pouvez pas le faire car certains processus ont un fichier ouvert. Si vous n'avez pas ces commandes disponibles, vous pouvez demander en /proctant que root:

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

ou, en tant qu'utilisateur mortel:

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

Martinwguy
la source
La méthode `ls -l 'fonctionne pour Linux mais ne semble pas fonctionner pour CygWin: il n'y a aucune information sur le verrouillage de fichier. Ne saurais-tu pas comment résoudre? Merci.
Sopalajo de Arrierez
Non, vous ne créez pas de fichier en lecture seule pour un verrou, car le fichier sera toujours présent lorsque votre application se bloquera. Forcer l'utilisateur à nettoyer la merde après l'application bloquée est mental.
polkovnikov.ph
6

Si vous voulez savoir quel descripteur de fichier est lié à votre fichier sans lsofou fuser- effectuez une recherche dans /proc:

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

Remplacez $1par le nom de fichier ouvert que vous recherchez. Vous pouvez modifier le -printfpour tout ce que vous voulez voir, ou egrep -o '[0-9]+' | head -1utiliser pour les informations de ce processus.ps -Fp <pid>

La réponse de @fin est évidemment la meilleure solution, mais pour répondre au commentaire de @ JoseLSegura , si ce n'est pas disponible, la solution ci-dessus était ma réponse.$ lsof <filename>

Scott
la source
2

J'ai trouvé que l'utilisation de la réponse acceptée ne répertoriait pas les processus utilisant mon répertoire (Ubuntu 14.04).

En fin de compte, j'ai utilisé lsof (liste des fichiers ouverts) et salué sa sortie pour trouver le processus incriminé:

lsof | egrep "<regexp-for-your-file>"
Eosis
la source
Un moyen plus propre et plus rapide pour cette utilisation lsofest son option -R. par exemple: lsof -R [filename]
tron5