Hướng dẫn dùng lệnh lsof cơ bản Image Hướng dẫn dùng lệnh lsof cơ bản

Bài viết này hướng dẫn dùng lệnh lsof cơ bản trên hệ điều hành Linux.

1. Giới thiệu lsof

Lệnh lsof(list open files) là lệnh được sử dụng để liệt kê thông tin về các tệp được mở bởi các quy trình khác nhau. Trong hệ điều hành Linux, mọi thứ là một tập tin(ví dụ như: pipes, sockets, directories, devices,...). Lệnh lsof được phát triển và hỗ trợ bởi Victor A. Abell. Chương trình sẽ liệt kê những tệp đang mở và tiến trình nào đang sử dụng chúng.

2. Cài đặt lsof

Lệnh lsof có sẵn trên hầu hết các bản phân phối Linux. Nếu không được cài đặt sẳn chúng ta thực hiện như sau:

  • Đối với bản phân phối Debian/Ubuntu:

    apt-get install lsof
    
  • Đối với với bản phân phối RHEL/CentOS:

    yum install lsof
    

3. Sử dụng lsof

3.1. Lệnh lsof với tập tin

👉 Ví dụ 1: Liệt kê tất cả các tệp đang mở

Lệnh lsof sẽ cung cấp danh sách tất cả các tệp đang mở thuộc về tất cả các quy trình đang hoạt động.

[root@test1 ~]# lsof
COMMAND   PID            USER    FD      TYPE             DEVICE    SIZE/OFF     NODE NAME
lsof      28207          root    0u      CHR              136,0       0t0          3 /dev/pts/0
lsof      28207          root    1u      CHR              136,0       0t0          3 /dev/pts/0
lsof      28207          root    2u      CHR              136,0       0t0          3 /dev/pts/0
lsof      28207          root    3r      DIR                0,3         0          1 /proc
lsof      28207          root    4r      DIR                0,3         0     231727 /proc/28207/fd
lsof      28207          root    5w     FIFO                0,9       0t0     231732 pipe
lsof      28207          root    6r     FIFO                0,9       0t0     231733 pipe
lsof      28208          root  cwd       DIR                8,2      4096    2097217 /root
lsof      28208          root  rtd       DIR                8,2       263         64 /
lsof      28208          root  txt       REG                8,2    154184    6505411 /usr/sbin/lsof
...

Theo mặc định một tệp được hiển thị trên mỗi dòng. Chúng ta sẽ tìm hiểu ý nghĩa của cột FD và TYPE:

Cột FD đại diện cho bộ mô tả tập tin. Một số giá trị thường gặp của FD là:

  • cwd: Thư mục làm việc hiện tại
  • txt: Tập tin văn bản
  • mem: Tập tin ánh xạ bộ nhớ
  • mmap: Thiết bị ánh xạ bộ nhớ
  • Number: Mô tả tập tin thực tế. Ký tự sau số biểu thị chế độ sau r để đọc, w để viết, u để đọc và viết.

Cột TYPE chỉ định loại tệp. Một số giá trị thường gặp của TYPE là:

  • REG: Tệp thông thường
  • DIR: Thư mục
  • FIFO: First In First Out
  • CHR: Tập tin character đặc biệt

Để tìm hiểu danh sách đầy đủ về FDTYPE chúng ta chạy lệnh sau: man lsof.

👉 Ví dụ 2: Liệt kê các tệp đã mở trong một thư mục

Để liệt kê các tệp đã mở trong một thư mục chúng ta sử dụng tùy chọn +D như bên dưới:

[root@test1 ~]# lsof +D /var/log/
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
rsyslogd 13071 root    5w   REG    8,2    11406 2103130 /var/log/messages
rsyslogd 13071 root    6w   REG    8,2     4692 2103128 /var/log/cron
rsyslogd 13071 root    7w   REG    8,2      678 2103131 /var/log/secure
auditd   13099 root    5w   REG    8,2  1249123 2419921 /var/log/audit/audit.log
tuned    13234 root    3w   REG    8,2    43507 6789997 /var/log/tuned/tuned.log

👉 Ví dụ 3: Liệt kê các tệp đã mở dựa vào tên tiến trình

Chúng ta có thể liệt kê các tệp được mở bằng tên tiến trình, sử dụng tùy chọn -c. Chúng ta thực hiện như bên dưới:

[root@test1 ~]# lsof -c ssh
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF    NODE NAME
sshd     8352 root  cwd    DIR                8,2      263      64 /
sshd     8352 root  rtd    DIR                8,2      263      64 /
sshd     8352 root  txt    REG                8,2   853040 6439738 /usr/sbin/sshd
sshd     8352 root  DEL    REG                8,2          6292703 /usr/lib64/libnss_files-2.17.so;5c94fef7
sshd     8352 root  mem    REG                8,2    68192 6382963 /usr/lib64/libbz2.so.1.0.6
sshd     8352 root  DEL    REG                8,2          6357643 /usr/lib64/libelf-0.170.so
...

👉 Ví dụ 4: Liệt kê các tệp được mở bởi một người dùng cụ thể

Để tìm danh sách các tệp được mở bởi một người dùng cụ thể sử dụng tùy chọn '-u'. Cú pháp như sau:

lsof -u user

Khi chúng ta muốn liệt kê các tệp được mở bởi các người dùng nhưng loại trừ 1 người dùng chúng ta sử dụng tùy chọn sau -u ^ thực hiện như bên dưới:

[root@test1 ~]# lsof -u ^dang
COMMAND      PID         USER    FD   TYPE             DEVICE      SIZE/OFF    NODE NAME
tuned     13234 13268    root    8u  a_inode               0,10         0       5074 [eventfd]
tuned     13234 13268    root    9r     FIFO                0,9       0t0      48048 pipe
tuned     13234 13268    root   10w     FIFO                0,9       0t0      48048 pipe
tuned     13234 13268    root   11w      CHR              10,61       0t0       6812 /dev/cpu_dma_latency
tuned     13234 13268    root   18u  a_inode               0,10         0       5074 [eventpoll]
udisksd   16939          root  cwd       DIR                8,2       263         64 /
udisksd   16939          root  rtd       DIR                8,2       263         64 /
udisksd   16939          root  txt       REG                8,2    434880   73402403 /usr/libexec/udisks2/udisksd
...

👉 Ví dụ 5: Liệt kê tất cả các tệp đang mở theo một tiến trình

Bạn có thể liệt kê tất cả các tệp được mở bởi một tiến trình cụ thể bằng tùy chọn -p.

[root@test1 ~]# lsof -p 8352
COMMAND  PID USER   FD   TYPE             DEVICE SIZE/OFF    NODE NAME
sshd    8352 root  cwd    DIR                8,2      263      64 /
sshd    8352 root  rtd    DIR                8,2      263      64 /
sshd    8352 root  txt    REG                8,2   853040 6439738 /usr/sbin/sshd
sshd    8352 root  DEL    REG                8,2          6292703 /usr/lib64/libnss_files-2.17.so;5c94fef7
sshd    8352 root  mem    REG                8,2    68192 6382963 /usr/lib64/libbz2.so.1.0.6
sshd    8352 root  DEL    REG                8,2          6357643 /usr/lib64/libelf-0.170.so
sshd    8352 root  mem    REG                8,2    19896 6383002 /usr/lib64/libattr.so.1.1.0
sshd    8352 root  mem    REG                8,2    15688 6383311 /usr/lib64/libkeyutils.so.1.5
sshd    8352 root  DEL    REG                8,2          6383629 /usr/lib64/libkrb5support.so.0.1;5c94fef7
sshd    8352 root  mem    REG                8,2    11448 6292340 /usr/lib64/libfreebl3.so
sshd    8352 root  mem    REG                8,2   251832 6357565 /usr/lib64/libnspr4.so
sshd    8352 root  mem    REG                8,2    20096 6357566 /usr/lib64/libplc4.so

👉 Ví dụ 7: Thực thi lsof trong chế độ lặp lại

Lệnh lsof có chế độ Lặp lại. Chế độ lặp lại có thể được bật bằng cách sử dụng tuỳ chọn -r hoặc +r. Nếu +r được sử dụng thì chế độ lặp lại sẽ kết thúc khi không tìm thấy tệp đang mở còn tùu chọn -r sẽ tiếp tục liệt kê, trì hoãn, liệt kê cho đến khi đưa ra bất kể các tệp có được mở hay không.

Các chu kỳ sẽ được phân tách bằng cách sử dụng '======='. Bạn cũng chỉ định thời gian trễ là '-r' | '+ r'.

[root@test1 ~]# lsof -c ssh -r5
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF    NODE NAME
sshd     8352 root  cwd    DIR                8,2      263      64 /
sshd     8352 root  rtd    DIR                8,2      263      64 /
sshd     8352 root  txt    REG                8,2   853040 6439738 /usr/sbin/sshd
sshd     8352 root  DEL    REG                8,2          6292703 /usr/lib64/libnss_files-2.17.so;5c94fef7
sshd     8352 root  mem    REG                8,2    68192 6382963 /usr/lib64/libbz2.so.1.0.6
sshd     8352 root  DEL    REG                8,2          6357643 /usr/lib64/libelf-0.170.so
...
=======
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF    NODE NAME
sshd     8352 root  cwd    DIR                8,2      263      64 /
sshd     8352 root  rtd    DIR                8,2      263      64 /
sshd     8352 root  txt    REG                8,2   853040 6439738 /usr/sbin/sshd
sshd     8352 root  DEL    REG                8,2          6292703 /usr/lib64/libnss_files-2.17.so;5c94fef7
sshd     8352 root  mem    REG                8,2    68192 6382963 /usr/lib64/libbz2.so.1.0.6

3.2. Lệnh lsof với tìm kiếm kết nối mạng

Kết nối mạng cũng là tập tin. Vì vậy, chúng tôi có thể tìm thấy thông tin họ bằng cách sử dụng lệnh lsof.

👉 Ví dụ 1: Hiển thị tất cả các kết nối mạng

Chúng ta có thể liệt kê tất cả các kết nối mạng được mở bằng cách sử dụng tùy chọn -i.

[root@test1 ~]# lsof -n -i
COMMAND    PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
chronyd    489 chrony    1u  IPv4  13504      0t0  UDP 127.0.0.1:323
chronyd    489 chrony    2u  IPv6  13505      0t0  UDP [::1]:323
dhclient   578   root    6u  IPv4  15376      0t0  UDP *:bootpc
dhclient   579   root    6u  IPv4  15365      0t0  UDP *:bootpc
sshd      8352   root    3u  IPv4  28174      0t0  TCP *:terminaldb (LISTEN)
sshd      8352   root    4u  IPv6  28176      0t0  TCP *:terminaldb (LISTEN)
master   13050   root   13u  IPv4  46933      0t0  TCP 127.0.0.1:smtp (LISTEN)
master   13050   root   14u  IPv6  46934      0t0  TCP [::1]:smtp (LISTEN)
sshd     29521   root    3u  IPv4 244046      0t0  TCP 102.96.126.130:terminaldb->26.79.26.92:50152 (ESTABLISHED)

Để nhận lưu lượng IPv6 với sử dụng tuỳ chọn -i 6. Cú pháp như bên dưới:

[root@localhost ~]# lsof -i 6 -n
COMMAND   PID   USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
chronyd  3024 chrony    2u  IPv6     13942      0t0  UDP [::1]:323
nginx    3259   root   28u  IPv6 185119976      0t0  TCP *:http (LISTEN)
nginx    3259   root   30u  IPv6 185119978      0t0  TCP *:https (LISTEN)
nginx    3261 nobody   28u  IPv6 185119976      0t0  TCP *:http (LISTEN)
nginx    3261 nobody   30u  IPv6 185119978      0t0  TCP *:https (LISTEN)
python  12539    bot    4u  IPv6 192427365      0t0  TCP [2400:8901::f03c:91ff:fefb:dba1]:46710->[2001:67c:4e8:f004::9]:https (ESTABLISHED)
sshd    26892   root    4u  IPv6    612238      0t0  TCP *:ssh (LISTEN)

👉 Ví dụ 2: Hiển thị các kết nối TCP hoặc UDP

Khi chúng ta muốn hiển thị các kết nối TCP hoặc UDP bằng cách cung cấp giao thức ngay sau tuỳ chọn -i.

[root@test1 ~]# lsof -n -iUDP
COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
chronyd  489 chrony    1u  IPv4  13504      0t0  UDP 127.0.0.1:323
chronyd  489 chrony    2u  IPv6  13505      0t0  UDP [::1]:323
dhclient 578   root    6u  IPv4  15376      0t0  UDP *:bootpc
dhclient 579   root    6u  IPv4  15365      0t0  UDP *:bootpc
[root@test1 ~]# lsof -n -iTCP
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd     8352 root    3u  IPv4  28174      0t0  TCP *:terminaldb (LISTEN)
sshd     8352 root    4u  IPv6  28176      0t0  TCP *:terminaldb (LISTEN)
master  13050 root   13u  IPv4  46933      0t0  TCP 127.0.0.1:smtp (LISTEN)
master  13050 root   14u  IPv6  46934      0t0  TCP [::1]:smtp (LISTEN)
sshd    29521 root    3u  IPv4 244046      0t0  TCP 102.96.126.130:terminaldb->26.79.26.92:50152 (ESTABLISHED)

👉 Ví dụ 3: Hiển thị mạng liên quan đến một cổng nhất định

Bằng cách sử dụng tuỳ chọn -i :port bạn có thể hiển thị các kết nối mạng qua một cổng nhất định.

[root@test1 ~]# lsof -i :25
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
master  13050 root   13u  IPv4  46933      0t0  TCP localhost:smtp (LISTEN)
master  13050 root   14u  IPv6  46934      0t0  TCP localhost:smtp (LISTEN)

👉 Ví dụ 4: Hiển thị kết nối đến một máy chủ cụ thể

Bằng cách sử dụng tuỳ chọn -i@host chúng ta có thể hiển thị kết nối đến một máy chủ cụ thể. Thực hiện như sau:

[root@test1 ~]# lsof -n -i@102.96.126.130
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd    29521 root    3u  IPv4 244046      0t0  TCP 102.96.126.130:terminaldb->26.79.26.92:50152 (ESTABLISHED)

👉 Ví dụ 5: Tìm các tiến trình có trạng thái TCP là LISTEN

Để tìm các cổng đang chờ kết nối. Cú pháp như sau:

lsof -i -sTCP:LISTEN

Bạn cũng có thể thực hiện bằng cách dùng lệnh grep cho LISTEN.

[root@test1 ~]# lsof -n -i -sTCP:LISTEN
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd     8352 root    3u  IPv4  28174      0t0  TCP *:terminaldb (LISTEN)
sshd     8352 root    4u  IPv6  28176      0t0  TCP *:terminaldb (LISTEN)
master  13050 root   13u  IPv4  46933      0t0  TCP 127.0.0.1:smtp (LISTEN)
master  13050 root   14u  IPv6  46934      0t0  TCP [::1]:smtp (LISTEN)

👉 Ví dụ 6: Tìm tiến trình có trạng thái TCP là sTCP:ESTABLISHED

Bạn có thể hiển thị bất kỳ kết nối nào đã được thiết lập. Cú pháp như sau:

lsof -i -sTCP:ESTABLISHED

Bạn cũng có thể thực hiện bằng cách dùng lệnh grep cho ESTABLISHED.

[root@test1 ~]# lsof -n -i -sTCP:ESTABLISHED
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd    29521 root    3u  IPv4 244046      0t0  TCP 102.96.126.130:terminaldb->26.79.26.92:50152 (ESTABLISHED)

👉 Ví dụ 7: Chỉ ra các kết nối mà một user đang kết nối tới một host

Chúng ta có thể liệt kê các kết nối mà một user đang kết nối tới một host. Trong ví dụ naà thì user dang kết nối với 102.96.126.130 như bên dưới:

[root@test1 ~]# lsof -n -u dang -i @102.96.126.130
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd    30071 root    3u  IPv4 250523      0t0  TCP 102.96.126.130:terminaldb->26.79.26.92:50152 (ESTABLISHED)

Sử dụng các tùy chọn -t-c để xử lý HUP cú pháp như sau:

kill -HUP `lsof -t -c sshd`

Trong đó ý nghĩa các lệnh như sau:

  • -HUP: Để khởi động lại một tiến trình.
  • -t: Đầu ra ngắn gọn bằng ID của tiến trình
  • -c: Liệt kê các tệp đã mở dựa vào tên tiến trình

Cú pháp trên dùng để khởi động lại một tiến trình sshd.

👉 Ví dụ 9: Hiển thị các kết nối với một port trong phạm vi

Chúng ta có thể hiển thị các kết nối với một port trong phạm vi cú pháp như sau:

lsof -i @fw.google.com:2050=2580

5. Lời kết

Qua bài trên, cho chúng ta biết cách dùng lệnh lsof để liệt kê thông tin về các tệp được, kết nối mạng được mở bởi các tiến trình khác nhau trên hệ điều hành Linux.