Як визначити, який процес відкритий у Linux?


115

Я хочу визначити, який процес має право власності на файл-замок. Файли блокування - це просто файл з певним ім'ям, створеним.

Отже, як я можу визначити, який процес має відкритий файл у Linux? Бажано, щоб оптимальним був тип з одним лайнером або конкретне рішення для інструментів Linux.

Відповіді:


51

Також можна використовувати fuser для цього:

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

це було здорово, але використовувати його в сценарії я повинен був перевірити довжину виходу.
chovy

що ви маєте на увазі вихідну довжину?
Nathan Fellman

if [ fuser "$ file" `]; потім вийти '
chovy

1
fuser має дивну поведінку з кодами виходу. вона повертає 1 вихідний код з двома станами: A / деяка внутрішня помилка, перевірений файл не знайдений і т.д., B / no process відкрив вказаний файл. У ситуації A / деяке повідомлення про помилку друкується на його виході. На жаль, коли файл доступний і відкритий чимось, вихід генерується, але з кодом виходу 0. Було б краще, якщо ф'юзер вийде з трьома кодами, а не двома, як зараз. lsoft трохи гірше вирішити, тому що це працює більш повільно.
Znik

Це, по суті, така ж схема ls слід - повертає код виходу 2, якщо виникла помилка (наприклад, вказано недійсний параметр) або файл не знайдено (і 0, якщо він успішно передає інформацію).
Scott

138

На більшості систем Linux lsof NAME виконує завдання:

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
А що, якщо у вас немає lsof?
JoseLSegura

3
@JoseLSegura: Я припускаю, що ви досить спритні для відповіді "потім встановити lsof", щоб бути марним для вас. Ви можете докладно розповісти про свою проблему? Якщо у вас немає кореня, ви, швидше за все, не маєте привілеїв, щоб дізнатися, чи відкритий файл іншим користувачем.
Michael Scheper

8

Відкриття файлу не є блокуванням, оскільки, якщо кожен процес повинен перевірити, чи файл відкритий першим і не продовжувати, якщо він є, або створити / відкрити його, якщо він не є, то два процеси можуть цілком перевірити одночасно, обидва знаходять що він не відкритий, то і створити або відкрити його.

Щоб використовувати файл як блокування, операція перевірки та блокування повинна бути однією операцією безперервної дії. Цього можна досягти у файловій системі Unix, створивши файл з режимом лише для читання та видаливши його для розблокування. Якщо файл існує (і є лише читанням), створення файлу не вдасться, тому ви отримуєте перевірку та блокування в одній атомній операції.

Якщо процес блокування - це сценарій оболонки, який буде працювати як демон, цей ефект можна отримати за допомогою umask, налаштування кожного процесу, що встановлює дозволи, які створюються новими файлами за допомогою:

oldumask=$(umask)
umask 222   # create files unwritable to owner too
if echo $$ > /var/lock/foo
then
    : locking succeeded
else
    : locking failed
fi
umask $oldumask
Це також записує PID процесу власності у файл, що вирішує вашу іншу проблему: cat /var/lock/foo
Що стосується конкретного питання "Які процеси мають цей файл відкритим?", Це може бути корисним, коли ви хочете відмовитися від файлової системи, але не можете, тому що якийсь процес має відкритий файл у ньому. Якщо у вас немає таких доступних команд, ви можете запитати /proc як корінь:

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

або, як смертельний користувач:

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


Метод `ls -l 'працює для Linux, але, здається, не працює для CygWin: немає інформації про блокування файлів там. Хіба ви не знаєте, як вирішити? Дякую.
Sopalajo de Arrierez

Ні, ви не створюєте файл "лише для читання" для блокування, оскільки, коли пристрій зірветься, файл все одно залишиться. Примушуючи користувача прояснити лайно після того, як ваш розбитий додаток розумний.
polkovnikov.ph

4

Якщо ви хочете дізнатися, який точний дескриптор файлу посилається на ваш файл без lsof або fuser - пошук через /proc:

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

Замінити $1 з відкритим ім'ям файлу, який ви шукаєте. Ви можете внести зміни до -printf за те, що ви хочете побачити, або проникнути egrep -o '[0-9]+' | head -1 для використання з ps -Fp  & lt; pid & gt; для інформації цього процесу.

The $ lsof & lt; ім'я файлу & gt; Відповідь @fin це найкраща відповідь, очевидно, але відповісти Коментар @ JoseLSegura , якщо це недоступно, рішення вище було моєю відповіддю.


2

Я виявив, що використання прийнятої відповіді не містить переліку процесів, які використовували мій каталог (ubuntu 14.04).

Врешті-решт, я використав lsof (список відкритих файлів) і підкріпив його вихідні дані, щоб знайти процес порушення:

lsof | egrep "<regexp-for-your-file>"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.