Jak mogę ustalić, jaki proces ma otwarty plik w systemie Linux?

124

Chciałbym ustalić, który proces ma własność pliku blokady. Pliki blokady to po prostu plik o określonej nazwie, który został utworzony.

Jak więc ustalić, który proces ma otwarty konkretny plik w systemie Linux? Najlepszym rozwiązaniem byłby typ z jedną linią lub konkretne narzędzie dla systemu Linux.

Danny
źródło

Odpowiedzi:

55

Możesz również użyć fuserdo tego:

~> 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
źródło
to było świetne, ale aby użyć go w skrypcie, musiałem sprawdzić długość wyjściową.
chovy,
co masz na myśli długość wyjściową?
Nathan Fellman
if [ fuser „$ file” ']; następnie exit`
chovy
1
utrwalacz ma dziwne zachowanie z kodami wyjścia. zwraca 1 kod wyjścia z dwoma stanami: A / jakiś błąd wewnętrzny, nie znaleziono sprawdzonego pliku itp., B / brak procesu otworzył określony plik. W sytuacji A / jakiś komunikat o błędzie jest drukowany na jego wyjściu. Niestety, gdy plik jest dostępny i otwierany przez coś, generowane jest wyjście, ale z kodem wyjścia 0. Lepiej byłoby, gdyby fuser zakończył z trzema kodami, a nie dwoma jak obecnie. lsoft jest nieco gorszym rozwiązaniem, ponieważ działa wolniej.
Znik
Jest to zasadniczo ten sam wzór, który lsnastępuje - zwraca kod wyjścia 2, jeśli wystąpi błąd (np. Podano niepoprawną opcję) lub plik nie został znaleziony (i 0, jeśli pomyślnie zgłosi informacje).
Scott,
144

W większości systemów Linux lsof NAMEdziała:

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:~$
płetwa
źródło
4
A co jeśli nie masz lsof?
JoseLSegura
3
@JoseLSegura: Zakładam, że jesteś wystarczająco zaradny, aby odpowiedź „następnie zainstaluj lsof” była dla Ciebie bezużyteczna. Czy możesz rozwinąć swój problem? Jeśli nie masz roota, najprawdopodobniej nie masz uprawnień, aby dowiedzieć się, czy inny użytkownik mimo to ma otwarty plik.
Michael Scheper,
wydaje się, że to nie działa w przypadku plików, tylko dla katalogów
Jason
@Jason: działa dla plików, ale cwdwiersze (które zgłaszają użycie jako bieżący katalog roboczy procesu) zgłaszają tylko katalogi.
reinierpost
9

Otwarcie pliku nie jest blokadą, ponieważ jeśli każdy proces musi najpierw sprawdzić, czy plik jest otwarty i nie kontynuować, jeśli jest, lub utworzyć / otworzyć, jeśli nie jest, wówczas dwa procesy mogą całkiem dobrze sprawdzić jednocześnie, oba że nie jest otwarty, a następnie obaj go utwórz lub otwórz.

Aby użyć pliku jako blokady, operacja sprawdzania i blokowania musi być pojedynczą operacją nieprzerwaną. Możesz to osiągnąć w systemie plików Unix, tworząc plik w trybie tylko do odczytu i usuwając go, aby odblokować. Jeśli plik istnieje (i jest tylko do odczytu), tworzenie pliku zakończy się niepowodzeniem, więc otrzymujesz sprawdzenie i zablokowanie w pojedynczej operacji atomowej.

Jeśli twój proces blokowania jest skryptem powłoki, który będzie działał jako demon, możesz uzyskać ten efekt, używając umaskustawienia na proces, które określa uprawnienia, z którymi tworzone są nowe pliki:

oldumask = $ (umask)
umask 222 # twórz również pliki, których właściciel nie może zapisać
if echo $$> / var / lock / foo
następnie
    : blokowanie powiodło się
jeszcze
    : blokowanie nie powiodło się
fi
umask $ oldumask
Spowoduje to również zapisanie PID procesu właściciela w pliku, co rozwiązuje inny problem: cat /var/lock/foo
Jeśli chodzi o konkretne pytanie „Które procesy mają ten plik otwarty?”, Może to być przydatne, gdy chcesz odmontować system plików, ale nie może, ponieważ w niektórych procesach jest otwarty plik. Jeśli nie masz dostępnych tych poleceń, możesz zapytać /procjako root:

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

lub jako śmiertelny użytkownik:

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

martinwguy
źródło
metoda `ls -l 'działa dla Linuksa, ale wydaje się, że nie działa dla CygWin: nie ma tam informacji o blokowaniu plików. Czy nie wiesz jak rozwiązać? Dzięki.
Sopalajo de Arrierez
Nie, nie tworzysz pliku tylko do odczytu dla blokady, ponieważ gdy nastąpi awaria aplikacji, plik nadal będzie dostępny. Zmuszanie użytkownika do wyczyszczenia bzdur po tym, jak aplikacja uległa awarii.
polkovnikov.ph
6

Jeśli chcesz wiedzieć, który deskryptor pliku procesu prowadzi do twojego pliku bez lsoflub fuser- szukaj przez /proc:

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

Zastąp $1otwartą nazwą pliku, którego szukasz. Można dokonać zmian -printf, o cokolwiek chcecie, aby zobaczyć, czy rury do egrep -o '[0-9]+' | head -1do stosowania dla tego procesu jest informacją.ps -Fp <pid>

Odpowiedź przez @fin jest najlepszą odpowiedź, oczywiście, ale odpowiedzieć @ komentarzu JoseLSegura użytkownika , jeśli nie jest to możliwe, nad rozwiązaniem była moja odpowiedź.$ lsof <filename>

Scott
źródło
2

Stwierdziłem, że użycie zaakceptowanej odpowiedzi nie wymieniało procesów korzystających z mojego katalogu (ubuntu 14.04).

Na koniec użyłem lsof (lista otwartych plików) i grep wypisałem jego dane wyjściowe, aby znaleźć proces obrażający:

lsof | egrep "<regexp-for-your-file>"
Eosis
źródło
Bardziej czystym i szybszym sposobem na użycie tego lsofjest jego opcja -R. np .: lsof -R [filename]
tron5