Trong Linux, nhiều đối tượng được coi là một tệp, bất kể đối tượng đó thực sự là tệp, thiết bị, thư mục hoặc ổ cắm. Liệt kê một tập tin là dễ dàng, có vỏ được tích hợp sẵn ls
cho điều đó. Nhưng nếu người dùng muốn xem những tập tin nào hiện đang được mở bởi quy trình máy chủ web thì sao? Hoặc nếu người dùng đó muốn tìm ra tập tin nào được mở trong một thư mục nhất định? Đó là nơi lsof
diễn ra. Hãy tưởng tượng lsof
như là một ls
sự bổ sung của "tập tin mở".
Xin lưu ý rằng mặc dù BSD có một tiện ích khác cho công việc này fstat
, một số hương vị khác của Unix (ví dụ Solaris) cũng sở hữu lsof
. Các tùy chọn và cờ khác nhau trên các nền tảng khác, cũng như giao diện của đầu ra, nhưng nhìn chung kiến thức trong bài viết này cũng nên được áp dụng cho chúng.
Đầu tiên, chúng ta hãy xem định dạng của lsof
đầu ra và cách đọc. Đầu ra thông thường lsof
không có bất kỳ tham số nào sẽ giống như sau. Điều này đã được cắt tỉa để dễ đọc.
COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
init 1 root cwd DIR 254,1 4096 2 /
init 1 root rtd DIR 254,1 4096 2 /
init 1 root txt REG 254,1 36992 7077928 /sbin/init
init 1 root mem REG 254,1 14768 7340043 /lib/x86_64-linux-gnu/libdl-2.13.so
init 1 root mem REG 254,1 1603600 7340040 /lib/x86_64-linux-gnu/libc-2.13.so
init 1 root mem REG 254,1 126232 7340078 /lib/x86_64-linux-gnu/libselinux.so.1
init 1 root mem REG 254,1 261184 7340083 /lib/x86_64-linux-gnu/libsepol.so.1
init 1 root mem REG 254,1 136936 7340037 /lib/x86_64-linux-gnu/ld-2.13.so
init 1 root 10u FIFO 0,14 0t0 4781 /run/initctl
Các cột này có nghĩa như sau:
- LỰA CHỌN - Quá trình mà một tệp mở thuộc về, trong ví dụ này, mọi thứ đều liên quan đến
init
.
- PID - Số nhận dạng quy trình của quy trình nói trên.
- NGƯỜI DÙNG - Người dùng mà quá trình chạy theo. Đối với
init
, nó hầu như luôn luôn root
.
- FD - Bộ mô tả tệp của tệp, phổ biến nhất:
cwd
- Thư mục làm việc hiện tại (bạn có thể nhận thấy sự tương tự với pwd
lệnh in thư mục làm việc hiện tại).
rtd
- Thư mục gốc của một quá trình.
txt
- A text file
, điều này có thể có nghĩa là một tệp cấu hình liên quan đến quy trình hoặc "mã nguồn" liên quan đến (hoặc thuộc về) quy trình.
mem
- Một cái gọi là "tập tin ánh xạ bộ nhớ", có nghĩa là một đoạn bộ nhớ ảo (đọc: RAM) đã được gán cho một tập tin.
- Một số - số đại diện cho bộ mô tả tệp thực tế, ký tự sau số đó là chế độ mà tệp được mở:
r
- Đọc.
w
- Viết.
u
- Đọc và viết.
- TYPE - Chỉ định loại thực tế của tệp, phổ biến nhất là:
REG
- Một tập tin thường xuyên.
DIR
- Một thư mục.
FIFO
- Vào trước ra trước.
- THIẾT BỊ - Số chính và số phụ của thiết bị chứa tệp.
- KÍCH THƯỚC - Kích thước của tệp, tính bằng byte.
- NODE - Số inode của tệp.
- NAME - Tên của tệp.
Điều này có thể hơi quá sức bây giờ, nhưng nếu bạn làm việc với lsof
một vài lần, nó sẽ nhanh chóng chìm vào não của bạn.
Như đã đề cập ở trên, đầu ra của lsof
đã được rút ngắn ở đây. Không có bất kỳ đối số hoặc bộ lọc, lsof
tạo ra hàng trăm dòng đầu ra sẽ chỉ khiến bạn bối rối.
Có hai cách tiếp cận cơ bản để giải quyết vấn đề đó:
- Sử dụng một hoặc nhiều
lsof
tùy chọn dòng lệnh để thu hẹp kết quả.
- Ống dẫn đầu ra thông qua, ví dụ ,
grep
.
Mặc dù tùy chọn thứ hai nghe có vẻ thoải mái hơn vì bạn sẽ không phải ghi nhớ các lsof
tùy chọn dòng lệnh, nhưng nhìn chung nó không linh hoạt và hiệu quả, vì vậy chúng tôi sẽ sử dụng tùy chọn đầu tiên.
Hãy tưởng tượng rằng bạn muốn mở một tệp bằng trình soạn thảo văn bản yêu thích của mình và trình soạn thảo văn bản đó cho bạn biết rằng nó chỉ có thể được mở ở chế độ chỉ đọc vì một chương trình khác đã truy cập vào nó. lsof
sẽ giúp bạn tìm ra ai là thủ phạm:
lsof /path/to/your/file
Điều này sẽ tạo ra một đầu ra tương tự như thế này:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
vim 2679 root 5w REG 254,1 121525 6035622 /root/lsof.txt
Rõ ràng, bạn đã quên đóng cửa và phiên cũ hơn! Một vấn đề tương tự xảy ra khi bạn cố gắng ngắt kết nối một chia sẻ NFS và umount
cho bạn biết điều đó không thể vì một cái gì đó vẫn đang truy cập vào thư mục được gắn kết. Một lần nữa, lsof
có thể giúp bạn xác định thủ phạm:
lsof +D /path/to/your/directory/
Lưu ý dấu gạch chéo, đó là quan trọng. Nếu không lsof
sẽ cho rằng bạn có nghĩa là một tập tin thông thường. Đừng nhầm lẫn +
trước cờ - lsof
có rất nhiều tùy chọn dòng lệnh mà nó cần +
ngoài phổ biến hơn -
. Đầu ra sẽ như thế này:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mocp 5637 music 4r REG 0,19 10147719 102367344 /home/Music/RMS_GNU_SONG.ogg
Điều đó có nghĩa là quá trình mocp
, với PID 5637
, thuộc về người dùng music
đã mở một tệp được gọi RMS_GNU_SONG.ogg
. Tuy nhiên, ngay cả sau khi đóng quá trình đó, vẫn còn một vấn đề - khối lượng NFS không thể vượt qua.
lsof
có một -c
cờ hiển thị các tệp đã mở một tên quy trình tùy ý.
lsof -c mocp
Điều đó sẽ tạo ra một đầu ra trông như thế này:
mocp 9383 music 4r REG 0,19 10147719 102367344 /home/Music/ANOTHER_RMS_GNU_SONG.ogg
Trong ví dụ này, có một ví dụ khác về mocp
việc chạy, ngăn bạn ngắt kết nối chia sẻ. Sau khi tắt quá trình đó, bạn muốn đảm bảo rằng người dùng music
không có tệp nào có khả năng mở khác. lsof
có một -u
cờ để hiển thị các tập tin được mở bởi một người dùng cụ thể. Hãy nhớ rằng, một tệp không phải lúc nào cũng chỉ là một tệp thông thường trên đĩa cứng của bạn!
lsof -u music
Bạn cũng có thể vượt qua nhiều người dùng, cách nhau bằng dấu phẩy:
lsof -u music,moremusic
Một lưu ý quan trọng về hành vi mặc định của lsof
: các kết quả được dựa trên OR , có nghĩa là bạn sẽ thấy kết quả tệp được mở bởi các quy trình thuộc sở hữu của người dùng music
hoặc người dùng moremusic
. Nếu bạn muốn xem kết quả khớp các quy trình thuộc sở hữu của cả hai người dùng, thì bạn sẽ phải vượt qua cờ -a
:
lsof -au music, moremusic
Vì cả hai người dùng đều ở trong nhóm musicusers
, nên bạn cũng có thể liệt kê các tệp dựa trên nhóm:
lsof -g musicusers
Bạn cũng có thể kết hợp các cờ dòng lệnh:
lsof -u music,moremusic -c mocp
or
lsof -u ^music +D /home/Music
Trong dòng cuối cùng, chúng tôi đã thêm một lá cờ đặc biệt khác - ^
, viết tắt của logic KHÔNG . Nếu đầu ra trống sau khi chạy lệnh đó, thì việc ngắt kết nối rất có thể sẽ thành công.
Trong các ví dụ trước, chúng tôi chủ yếu xem xét các tệp thông thường. Làm thế nào về ổ cắm và kết nối mạng?
Để liệt kê tất cả các kết nối mạng hiện tại lsof
có -i
cờ:
lsof -i
Đầu ra trông giống như những gì chúng ta đã thấy cho đến nay ...
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
owncloud 3509 myuser 25u IPv4 44946 0t0 TCP strix.local:34217->myserver.vultr.com:https (ESTABLISHED)
firefox 3612 myuser 82u IPv4 49663 0t0 TCP strix.local:43897->we-in-f100.1e100.net:https (ESTABLISHED)
ssh 3784 myuser 3u IPv4 10437 0t0 TCP strix.local:51416->someserver.in:ssh (ESTABLISHED)
wget 4140 myuser 3w IPv4 45586 0t0 TCP strix.local:54460->media.ccc.de:http (CLOSE_WAIT)
... ngoại trừ một điểm khác biệt: thay vì tên tệp hoặc thư mục, cột NAME
hiện hiển thị thông tin kết nối. Mỗi kết nối bao gồm các phần sau:
- Giao thức.
- Tên máy chủ địa phương.
- Cổng nguồn của kết nối.
- Tên DNS đích.
- Cảng đích.
- Tình trạng kết nối.
Cũng như nhiều công cụ khác, bạn có thể từ chối phân giải tên và cổng DNS ( -n
và -P
, tương ứng). Cờ -i
có các tham số bổ sung. Bạn có thể chỉ định có hiển thị hay không tcp
, udp
hoặc icmp
kết nối hoặc một số cổng nhất định:
lsof -i :25
or
lsof -i :smtp
Một lần nữa, các tham số có thể được kết hợp. Ví dụ sau ...
lsof -i tcp:80
... sẽ chỉ hiển thị cho bạn các kết nối TCP bằng cổng 80. Bạn cũng có thể kết hợp nó với các tùy chọn mà bạn đã biết từ các tệp "cổ điển":
lsof -a -u httpd -i tcp
Điều này sẽ hiển thị cho bạn tất cả các kết nối TCP được mở bởi người dùng httpd
. Lưu ý -a
cờ, thay đổi hành vi mặc định của lsof
(như đã đề cập trước đó). Như với hầu hết các công cụ dòng lệnh, bạn có thể đi sâu vô cùng. Phần sau đây sẽ chỉ hiển thị cho bạn các kết nối TCP có trạng thái là "THÀNH LẬP":
lsof -i -s TCP:ESTABLISHED
Tại thời điểm này, bạn nên có một sự hiểu biết cơ bản về cách thức lsof
hoạt động, cùng với một số trường hợp sử dụng phổ biến. Để đọc thêm, hãy xem trang chủ lsof
của hệ thống của bạn.