Come posso determinare quale processo ha un file aperto in Linux?


124

Vorrei determinare quale processo ha la proprietà di un file di blocco. I file di blocco sono semplicemente un file con un nome specifico che è stato creato.

Quindi, come posso determinare quale processo ha un determinato file aperto in Linux? Preferibilmente un tipo a linea singola o una particolare soluzione di strumento Linux sarebbe ottimale.

Risposte:


55

Puoi anche usare fuserper questo:

~> less .vimrc
# put in background
~> fuser .vimrc
.vimrc:              28135
~> ps 28135
  PID TTY      STAT   TIME COMMAND
28135 pts/36   T      0:00 less .vimrc

è stato fantastico, ma per usarlo in uno script ho dovuto controllare la lunghezza dell'output.
amorevole

cosa intendi per lunghezza d'uscita?
Nathan Fellman,

if [ fusore "$ file" `]; poi esci`
chovy

1
il fusore ha un comportamento strano con i codici di uscita. restituisce 1 codice di uscita con due stati: A / qualche errore interno, file verificato non trovato ecc., B / nessun processo ha aperto il file specificato. Nella situazione A / un messaggio di errore viene stampato sul suo output. Sfortunatamente quando il file è disponibile e aperto da qualcosa, l'output viene generato ma con il codice di uscita 0. Sarebbe meglio se il fusore uscisse con tre codici, non due come attualmente. lsoft è un po 'peggio, perché funziona più lentamente.
Znik,

Questo è essenzialmente lo stesso modello che lssegue: restituisce il codice di uscita 2 in caso di errore (ad es. Opzione non valida specificata) o file non trovato (e 0 se riporta correttamente informazioni).
Scott,

144

Sulla maggior parte dei sistemi Linux lsof NAMEfa il lavoro:

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:~$

4
E se non hai lsof?
JoseLSegura,

3
@JoseLSegura: suppongo che tu sia abbastanza pieno di risorse perché la risposta 'quindi installa lsof' sia inutile per te. Puoi approfondire il tuo problema? Se non hai root, probabilmente non hai i priv per scoprire se un altro utente ha comunque aperto il file.
Michael Scheper,

questo non sembra funzionare per i file, ma solo per i dir
Jason,

@Jason: funziona per i file, ma le cwdrighe (che indicano l'uso come directory di lavoro corrente di un processo) riportano solo le directory.
reinierpost,

9

Avere un file aperto non è un blocco perché, se ogni processo deve verificare se il file è aperto per primo e non procedere se lo è o crearlo / aprirlo se non lo è, allora due processi potrebbero controllare abbastanza contemporaneamente, entrambi trovano che non è aperto, quindi sia crearlo che aprirlo.

Per utilizzare un file come blocco, l'operazione di verifica e blocco deve essere un'unica operazione ininterrotta. Puoi farlo in un filesystem Unix creando un file con modalità di sola lettura e rimuovendolo per sbloccare. Se il file esiste (ed è di sola lettura) la creazione del file fallirà, quindi otterrai un controllo e un blocco in una singola operazione atomica.

Se il processo di blocco è uno script shell che verrà eseguito come daemon, è possibile ottenere questo effetto utilizzando umask, un'impostazione per processo che imposta le autorizzazioni con cui vengono creati i nuovi file:

oldumask = $ (umask)
umask 222 # crea file non scrivibili anche per il proprietario
se echo $$> / var / lock / foo
poi
    : blocco riuscito
altro
    : blocco fallito
fi
umask $ oldumask
Questo scrive anche il PID del processo proprietario nel file, risolvendo l'altro problema: cat /var/lock/foo
Per quanto riguarda la domanda specifica "Quali processi hanno questo file aperto?", Questo può essere utile quando si desidera smontare un filesystem ma non è possibile perché in alcuni processi è aperto un file. Se non hai questi comandi disponibili, puoi chiedere /proccome root:

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

o, come utente mortale:

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


il metodo `ls -l 'funziona per Linux ma sembra non funzionare per CygWin: non ci sono informazioni sul blocco dei file lì. Non sapresti risolvere? Grazie.
Sopalajo de Arrierez,

No, non crei file di sola lettura per un blocco, perché quando l'app si arresterà in modo anomalo, il file sarà ancora lì. Costringere l'utente a ripulire la merda dopo che l'app in crash è mentale.
polkovnikov.ph,

6

Se vuoi sapere quale descrittore di file del processo esatto collega al tuo file senza lsofo fuser- cerca tra /proc:

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

Sostituisci $1con il nome file aperto che stai cercando. È possibile modificare il -printfper quello che si desidera vedere, oppure può egrep -o '[0-9]+' | head -1essere utilizzato per le informazioni di quel processo.ps -Fp <pid>

La risposta di @fin è la risposta migliore, ovviamente, ma per rispondere al commento di @ JoseLSegura , se questa non è disponibile, la soluzione sopra era la mia risposta.$ lsof <filename>


2

Ho scoperto che l'uso della risposta accettata non elencava i processi che stavano usando la mia directory (ubuntu 14.04).

Alla fine, ho usato lsof (elenca i file aperti) e ho greppato il suo output per trovare il processo offensivo:

lsof | egrep "<regexp-for-your-file>"

Un modo più pulito e veloce per questo utilizzo lsofè la sua opzione -R. es: lsof -R [filename]
tron5
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.