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.