Làm cách nào để xác định quy trình nào có tệp mở trong Linux?


124

Tôi muốn xác định quy trình nào có quyền sở hữu tệp khóa. Các tệp khóa chỉ đơn giản là một tệp có tên cụ thể đã được tạo.

Vì vậy, làm thế nào tôi có thể xác định quá trình nào có một tệp cụ thể mở trong Linux? Tốt nhất là loại một lớp lót hoặc một giải pháp công cụ Linux cụ thể sẽ là tối ưu.

Câu trả lời:


55

Bạn cũng có thể sử dụng fusercho việc này:

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

Điều này thật tuyệt, nhưng để sử dụng nó trong một kịch bản, tôi phải kiểm tra độ dài đầu ra.
chovy

ý nghĩa của chiều dài đầu ra là gì?
Nathan Fellman

if [ bộ nhiệt áp "$ file" `]; sau đó exit`
chovy

1
fuser có hành vi lạ với mã thoát. nó trả về 1 mã thoát với hai trạng thái: A / một số lỗi nội bộ, không tìm thấy tệp đã kiểm tra, v.v. B / không có quá trình mở tệp được chỉ định. Trong tình huống A / một số thông báo lỗi được in ra đầu ra của nó. Thật không may khi tập tin có sẵn và được mở bởi một cái gì đó, đầu ra được tạo ra nhưng với mã thoát 0. Sẽ tốt hơn nếu fuser sẽ thoát với ba mã chứ không phải hai như hiện tại. Lsoft giải quyết kém hơn một chút vì điều này hoạt động chậm hơn.
Znik

Đây thực chất là cùng một mẫu lstheo sau - nó trả về mã thoát 2 nếu có lỗi (ví dụ: tùy chọn không hợp lệ được chỉ định) hoặc không tìm thấy tệp (và 0 nếu báo cáo thành công thông tin).
Scott

144

Trên hầu hết các hệ thống Linux đều lsof NAMEthực hiện công việc:

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
Và nếu bạn không có lsof thì sao?
JoseLSegura

3
@JoseLSegura: Tôi cho rằng bạn đủ tài nguyên cho câu trả lời 'sau đó cài đặt lsof' là vô ích đối với bạn. Bạn có thể giải thích vấn đề của bạn? Nếu bạn không có root, bạn có thể không có quyền riêng tư để tìm hiểu xem người dùng khác có mở tệp hay không.
Michael Scheper

điều này dường như không hoạt động đối với các tệp, chỉ dành cho thư mục
Jason

@Jason: nó hoạt động cho các tệp, nhưng cwdcác dòng (báo cáo sử dụng làm thư mục làm việc hiện tại của một tiến trình) chỉ báo cáo các thư mục.
Revierpost

9

Có một tệp mở không phải là khóa bởi vì, nếu mỗi quá trình phải kiểm tra xem tệp có được mở trước không và tiến hành nếu nó là hoặc tạo / mở nó nếu không, thì hai quá trình có thể kiểm tra đồng thời, cả hai đều tìm thấy rằng nó không mở, sau đó cả hai tạo hoặc mở nó.

Để sử dụng tệp dưới dạng khóa, thao tác kiểm tra và khóa phải là một thao tác không bị gián đoạn. Bạn có thể đạt được điều này trong hệ thống tệp Unix bằng cách tạo một tệp có chế độ chỉ đọc và xóa nó để mở khóa. Nếu tệp tồn tại (và chỉ đọc), việc tạo tệp sẽ thất bại, do đó bạn có thể kiểm tra và khóa trong một hoạt động nguyên tử duy nhất.

Nếu quy trình khóa của bạn là tập lệnh shell sẽ chạy dưới dạng daemon, bạn có thể nhận được hiệu ứng này bằng cách sử dụng umask, cài đặt theo quy trình đặt các quyền mà tệp mới được tạo với:

oldumask = $ (ô)
umask 222 # tạo tập tin không thể chấp nhận cho chủ sở hữu quá
nếu tiếng vang $$> / var / lock / foo
sau đó
    : khóa thành công
khác
    : khóa không thành công
fi
um $ $ oldumask
Điều này cũng ghi quá trình sở hữu 'PID vào tệp, giải quyết vấn đề khác của bạn: cat /var/lock/foo
Liên quan đến câu hỏi cụ thể "Quy trình nào mở tệp này?", Điều này có thể hữu ích khi bạn muốn ngắt kết nối hệ thống tệp nhưng không thể vì một số quy trình có tệp mở trong đó. Nếu bạn không có sẵn các lệnh đó, bạn có thể hỏi /procbằng root:

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

hoặc, với tư cách là người sử dụng:

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


phương thức `ls -l 'hoạt động với Linux nhưng dường như không hoạt động với CygWin: không có thông tin nào về việc khóa tệp ở đó. Bạn không biết làm thế nào để giải quyết? Cảm ơn.
Sopalajo de Arrierez

Không, bạn không tạo tệp chỉ đọc cho khóa, vì khi ứng dụng của bạn gặp sự cố, tệp sẽ vẫn ở đó. Buộc người dùng phải dọn dẹp rác rưởi sau khi ứng dụng bị sập của bạn là do tâm lý.
polkovnikov.ph

6

Nếu bạn muốn biết bộ mô tả tệp chính xác của quá trình liên kết đến tệp của bạn mà không lsofhoặc fuser- tìm kiếm thông qua /proc:

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

Thay thế $1bằng tên tệp mở mà bạn đang tìm kiếm. Bạn có thể sửa đổi -printfbất cứ điều gì bạn muốn xem, hoặc đưa vào egrep -o '[0-9]+' | head -1sử dụng cho thông tin của quy trình đó.ps -Fp <pid>

Câu trả lời của @fin là câu trả lời tốt nhất, rõ ràng, nhưng để trả lời bình luận của @ JoseLSegura , nếu điều này không có sẵn, giải pháp ở trên là câu trả lời của tôi.$ lsof <filename>


2

Tôi thấy rằng việc sử dụng câu trả lời được chấp nhận đã không liệt kê các quy trình đang sử dụng thư mục của tôi (ubfox 14.04).

Cuối cùng, tôi đã sử dụng lsof (liệt kê các tệp đang mở) và kết nối đầu ra của nó để tìm quá trình vi phạm:

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

Một cách sạch hơn và nhanh hơn cho việc sử dụng lsofnày là tùy chọn của nó -R. ví dụ: lsof -R [filename]
tron5
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.