文章目錄
命令介紹
常用選項
字段說明
文件類型
文件描述符
文件狀態模式
鎖模式
參考示例
(一)查看打開指定文件的所有進程
(二)列出由某個 PID 對應的進程打開的所有文件
(三)查看指定名稱的進程所打開的文件列表
(四)列出除了某個用戶以外的被打開的文件列表
(五)列出除了某個進程之外,其它進程打開的文件列表
(六)列出所有的網絡連接
(七)列出所有的 TCP 網絡連接
(八)列出所有的 UDP 網絡連接
(九)查看有哪些進程在使用指定的端口
(十)查看哪些進程在使用指定的 UDP 端口
(十一)查看哪些進程在使用指定的 TCP 端口
(十二)列出某個用戶所有活躍的網絡端口
(十三)查看指定用戶組所打開的文件列表
(十四)根據文件描述符的范圍查看有關的文件列表
(十五)哪些進程在使用 apache 的可執行文件
(十六)查看連接到某個遠程主機端口的進程
(十七)不斷查看遠程主機 ftp 連接的情況
(十八)遞歸查找某個目錄中所有打開的文件
(十九)列出某個用戶打開的所有文件
(二十)列出由某個用戶或某個進程打開的所有文件
(二十一)查看某個用戶的所有網絡連接
(二十二)列出所有內存映射文件
(二十三)列出所有加載在內存中並正在執行的進程
(二十四)查看使用網絡資源的進程 pid
(二十五)殺掉所有使用網絡的進程
(二十六)循環列出文件
(二十七)查看被打開的和網絡相關的文件
(二十八)統計系統打開的文件總數
(二十九)殺掉屬於某個用戶的打開了文件的所有進程
(三十)列出某個 IP 的網絡連接信息
(三十一)同時列出連接某主機多個端口的網絡連接文件
經典場景應用
(一)查看指定進程打開的特定文件(查看日志文件路徑)
(二)查看文件的內存映射路徑(查看已刪除文件的內容)
(三)恢復被刪除的文件
(四) 日志文件刪除后磁盤空間可用空間沒有變大,怎么解決
命令介紹
lsof 是 List Opened Files 的縮寫,該命令是用於列出當前系統打開的文件的工具,也就是查看被進程打開的文件的工具,且可以用來找回或恢復被刪除的文件。
在 Linux 下“一切皆文件”,任何事物都以文件的形式存在,包括但不限於 pipes, sockets, directories, devices等。通過文件不僅僅可以訪問常規數據,還可以訪問網絡連接和硬件,例如:傳輸控制協議 (TCP) 和用戶數據報協議 (UDP) 套接字等。
lsof 是一個 Linux 下的非常實用和方便的系統級的監控、診斷工具。因為 lsof 命令需要訪問核心內存和各種文件,所以必須以 root 用戶的身份運行它才能夠充分地發揮其功能。
系統在后台為每個應用程序分配了一個文件描述符(程序打開文件,系統都會分配一個文件描述符給該程序),該文件描述符為應用程序與基礎操作系統之間的交互提供了通用接口。因為應用程序打開文件的描述符列表提供了大量關於這個應用程序本身的信息,因此通過 lsof 工具查看這個列表,對系統監測以及排錯將是很有幫助的。
在 lsof 顯示的結果中,每行顯示一個打開的文件,若不指定條件默認顯示所有進程打開的所有文件。
常用選項
選項 說明
-a 指示多個選項之間為 與 的關系,必須都滿足時才顯示結果
-c<進程名> 列出指定進程所打開的文件
-g 顯示歸屬於 GID 的進程情況
-d<文件號> 列出占用該文件號的進程,文件號就是文件描述符。例如:顯示使用fd為4的進程
+d<目錄> 列出指定目錄下被打開的文件
+D<目錄> 遞歸列出指定目錄下被打開的文件
-n<目錄> 列出使用NFS的文件
-n 不解析主機名 ,不將 IP 轉換為 Host Name,缺省是不加上 -n 選項,疑問??
-i<條件> 列出符合條件的且與網絡相關的進程。(4、6、協議、:端口、 @ip )不加條件默認列出所有的網絡連接。
-p<進程號> 列出指定進程號所打開的文件
-P 不解析端口號
-N 列出所有NFS(網絡文件系統)文件
-u<用戶名> 列出指定用戶打開的文件, 該選項可以指定用戶名 或 user ID,可以通過逗號分隔多個用戶名稱或 user ID,也可以通過符號 ^ 對條件取反
-U 列出所有UNIX域Socket文件
-t 只輸出 PID
-h 顯示幫助信息
-v 顯示版本信息
字段說明
字段名稱 說明
COMMAND 進程的名稱,默認以 9 個字符長度顯示的命令名稱。可使用 +c 參數指定顯示的寬度,若 +c 后跟的參數為零,則顯示命令的全名。這個 +c 參數好像無效
PID 進程標識符
PPID 父進程標識符,父進程的IP號,默認不顯示,當使用 -R 參數可打開。
USER 進程所有者,命令的執行 UID 或系統中登陸的用戶名稱。默認顯示為用戶名,當使用 -l 參數時,可顯示 UID。
PGID 進程所屬組標識符,進程組的ID 編號,默認也不會顯示,當使用 -g 參數時可打開。
FD File Descriptor Number,文件描述符,應用程序通過文件描述符識別文件,例如:cwd、txt 等
TYPE 文件類型,例如: DIR、REG 等
DEVICE 指定磁盤的名稱,以逗號分隔設備編號,使用character special、block special表示的設備號
SIZE 文件的大小,如果不能用大小表示的,會留空。使用-s參數控制。
NODE 索引節點(文件在磁盤上的標識),本地文件的node碼,或者協議,如TCP等
NAME 打開文件的確切名稱,掛載點和文件的全路徑(鏈接會被解析為實際路徑),或者連接雙方的地址和端口、狀態等
文件類型
英文標識 說明
REG 普通文件
DIR 表示目錄
CHR 表示字符類型
BLK 塊設備類型
UNIX UNIX 域套接字,UNIX Domain Sockets
FIFO 先進先出 (FIFO) 隊列
IPv4/IPv6 網際協議 (IP) 套接字,IPv4/IPv6 套接字
LINK 鏈接文件
文件描述符
描述符 說明
cwd Current Work Director 的縮寫,應用程序的當前工作目錄,這是該應用程序啟動的目錄,除非它本身對這個目錄進行更改
txt 該類型的文件是程序代碼,表示程序的可執行文件
lnn library references (AIX)
er FD information error (see NAME column)
jld jail directory (FreeBSD)
ltx shared library text (code and data)
mxx hex memory-mapped type number xx
m86 DOS Merge mapped file
mem memory-mapped file,表示內存映射文件
mmap memory-mapped device
pd parent directory
rtd root directory,表示根目錄
tr kernel trace file (OpenBSD)
v86 VP/ix mapped file
0 表示標准輸出
1 表示標准輸入
2 表示標准錯誤
文件狀態模式
一般在標准輸出、標准錯誤、標准輸入后還跟着文件狀態模式。
文件狀態模式 說明
u 表示該文件被打開並處於讀取/寫入模式,例如:10u,10 是打開該文件時返回的一個整數,表示文件號是10,u 表示該文件被打開且處於讀取/寫入模式
r 表示該文件被打開並處於只讀模式
w 表示該文件被打開並處於只寫模式
space 表示該文件的狀態模式為 unknow,且沒有鎖定
- 表示該文件的狀態模式為 unknow,且被鎖定
鎖模式
在文件狀態模式后面,還跟着相關的鎖:
鎖模式 說明
N for a Solaris NFS lock of unknown type
r for read lock on part of the file
R for a read lock on the entire file
w for a write lock on part of the file(文件的部分寫鎖)
W for a write lock on the entire file(整個文件的寫鎖)。表示該應用程序擁有對整個文件的寫鎖(表示該進程擁有對文件寫操作的鎖),該文件描述符用於確保每次只能打開一個應用程序實例。初始打開每個應用程序時,都具有三個文件描述符,從 0 到 2,分別表示標准輸入、標准輸出和標准錯誤。所以大多數應用程序所打開的文件的 FD 都是從 3 開始。
u for a read and write lock of any length
U for a lock of unknown type
x for an SCO OpenServer Xenix lock on part of the file
X for an SCO OpenServer Xenix lock on the entire file
space if there is no lock。表示該文件的狀態模式為 unknow,且沒有鎖定。
- 表示該文件的狀態模式為 unknow,且被鎖定。
參考示例
(一)查看打開指定文件的所有進程
查看哪些進程正在使用文件 /var/log/mysqld.log:
[root@htlwk0001host ~]# lsof /var/log/mysqld.log
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 1064381 mysql 1w REG 253,1 3240699 935706 /var/log/mysqld.log
mysqld 1064381 mysql 2w REG 253,1 3240699 935706 /var/log/mysqld.log
1
2
3
4
哪些進程在占用文件 /etc/passwd:
[root@htlwk0001host ~]# lsof /etc/passwd
1
哪些進程在占用 hda6:
[root@htlwk0001host ~]# lsof /dev/hda6
1
哪些進程在占用光驅:
[root@htlwk0001host ~]# lsof /dev/cdrom
1
(二)列出由某個 PID 對應的進程打開的所有文件
查看 PID 為 1064381 的進程所打開的全部文件列表:
[root@htlwk0001host ~]# lsof -p 1064381
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 1064381 mysql cwd DIR 253,1 4096 636744 /var/lib/mysql
mysqld 1064381 mysql rtd DIR 253,1 244 128 /
mysqld 1064381 mysql txt REG 253,1 251816000 51228705 /usr/sbin/mysqld
mysqld 1064381 mysql mem REG 253,1 553480 50342901 /usr/lib64/libpcre2-8.so.0.7.1
mysqld 1064381 mysql mem REG 253,1 304848 50342907 /usr/lib64/libselinux.so.1
1
2
3
4
5
6
7
(三)查看指定名稱的進程所打開的文件列表
查看進程 mysqld 所打開的全部文件列表:
[root@htlwk0001host ~]# lsof -c mysqld
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 1064381 mysql cwd DIR 253,1 4096 636744 /var/lib/mysql
mysqld 1064381 mysql rtd DIR 253,1 244 128 /
mysqld 1064381 mysql txt REG 253,1 251816000 51228705 /usr/sbin/mysqld
mysqld 1064381 mysql mem REG 253,1 553480 50342901 /usr/lib64/libpcre2-8.so.0.7.1
mysqld 1064381 mysql mem REG 253,1 304848 50342907 /usr/lib64/libselinux.so.1
mysqld 1064381 mysql mem REG 253,1 33224 50343274 /usr/lib64/libuuid.so.1.3.0
-c 選項限定只列出以 mysqld 開頭的進程打開的文件:
你同樣可以制定多個 -c 參數:
[root@htlwk0001host ~]# lsof -c apache -c python
1
這會列出所有由 apache 和 python 打開的文件。
(四)列出除了某個用戶以外的被打開的文件列表
[root@htlwk0001host ~]# lsof -u ^root
COMMAND PID TID TASKCMD USER FD TYPE DEVICE SIZE/OFF NODE NAME
polkitd 715 polkitd cwd DIR 253,1 244 128 /
polkitd 715 polkitd rtd DIR 253,1 244 128 /
說明:^ 符號,表示 取反 的意思。
(五)列出除了某個進程之外,其它進程打開的文件列表
[root@htlwk0001host ~]# lsof -p ^1234
1
(六)列出所有的網絡連接
列出所有打開了網絡套接字(TCP和UDP)的進程:
[root@htlwk0001host ~]# lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
chronyd 743 chrony 5u IPv4 20334 0t0 UDP localhost:323
chronyd 743 chrony 6u IPv6 20335 0t0 UDP localhost:323
NetworkMa 901 root 24u IPv4 22817 0t0 UDP htlwk0001host:bootpc->_gateway:bootps
systemd-r 955 systemd-resolve 12u IPv4 23063 0t0 UDP *:hostmon
systemd-r 955 systemd-resolve 13u IPv4 23064 0t0 TCP *:hostmon (LISTEN)
1
2
3
4
5
6
7
(七)列出所有的 TCP 網絡連接
[root@htlwk0001host ~]# lsof -i tcp
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd-r 955 systemd-resolve 13u IPv4 23064 0t0 TCP *:hostmon (LISTEN)
systemd-r 955 systemd-resolve 15u IPv6 23067 0t0 TCP *:hostmon (LISTEN)
nginx 26556 root 8u IPv4 137518 0t0 TCP *:http (LISTEN)
nginx 26556 root 9u IPv4 137519 0t0 TCP *:https (LISTEN)
nginx 26556 root 10u IPv6 137520 0t0 TCP *:https (LISTEN)
nginx 26556 root 11u IPv6 137521 0t0 TCP *:http (LISTEN)
svnserve 34295 root 3u IPv4 182743 0t0 TCP *:svn (LISTEN)
httpd 34871 root 4u IPv6 186113 0t0 TCP *:tproxy (LISTEN)
tcp 選項會強制 lsof 只列出打開 TCP sockets 的進程。
(八)列出所有的 UDP 網絡連接
[root@htlwk0001host ~]# lsof -i udp
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
chronyd 743 chrony 5u IPv4 20334 0t0 UDP localhost:323
chronyd 743 chrony 6u IPv6 20335 0t0 UDP localhost:323
NetworkMa 901 root 24u IPv4 22817 0t0 UDP htlwk0001host:bootpc->_gateway:bootps
systemd-r 955 systemd-resolve 12u IPv4 23063 0t0 UDP *:hostmon
systemd-r 955 systemd-resolve 14u IPv6 23066 0t0 UDP *:hostmon
systemd-r 955 systemd-resolve 18u IPv4 23069 0t0 UDP 127.0.0.53:domain
(九)查看有哪些進程在使用指定的端口
讓 lsof 列出占用 TCP 或 UDP 的 3306 端口的進程:
[root@htlwk0001host ~]# lsof -i:3306
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 1050299 root 72u IPv6 19427946 0t0 TCP htlwk0001host:60664->47.114.59.224:mysql (ESTABLISHED)
java 1050299 root 78u IPv6 19427982 0t0 TCP htlwk0001host:60704->47.114.59.224:mysql (ESTABLISHED)
java 1050299 root 79u IPv6 19427963 0t0 TCP htlwk0001host:60684->47.114.59.224:mysql (ESTABLISHED)
java 1050299 root 80u IPv6 19427972 0t0 TCP htlwk0001host:60696->47.114.59.224:mysql (ESTABLISHED)
你也可以使用 /etc/services 中制定的端口名稱來代替端口號,比如:
[root@htlwk0001host ~]# lsof -i :smtp
1
(十)查看哪些進程在使用指定的 UDP 端口
[root@htlwk0001host ~]# lsof -i udp:55
1
(十一)查看哪些進程在使用指定的 TCP 端口
[root@htlwk0001host ~]# lsof -i tcp:55
1
(十二)列出某個用戶所有活躍的網絡端口
[root@htlwk0001host ~]# lsof -a -u test -i
1
(十三)查看指定用戶組所打開的文件列表
查找所有 PGID 為 5555 的進程打開的文件:
[root@htlwk0001host ~]# lsof -g 5555;
1
(十四)根據文件描述符的范圍查看有關的文件列表
顯示使用 fd 為 2-3 的進程:
[root@htlwk0001host ~]# lsof -d 2-3
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root 2u CHR 1,3 0t0 6597 /dev/null
systemd 1 root 3w CHR 1,11 0t0 6603 /dev/kmsg
1
2
3
4
上面的命令會列出所有描述符為 2 或 3 的文件。
顯示使用 fd 為 4 的進程:
[root@htlwk0001host ~]# lsof -d 4
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root 4u a_inode 0,14 0 9454 [eventpoll]
systemd-j 560 root 4u unix 0xffff944b07050480 0t0 11200 /run/systemd/journal/socket type=DGRAM
systemd-u 587 root 4u netlink 0t0 17814 KOBJECT_UEVENT
auditd 673 root 4u unix 0xffff944b2d4e8d80 0t0 380481 type=STREAM
1
2
3
4
5
6
上面這個命令會列出所有以描述符 4 打開的文件。
(十五)哪些進程在使用 apache 的可執行文件
[root@htlwk0001host ~]# lsof `which httpd`
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 34871 root txt REG 253,1 580064 53187782 /usr/sbin/httpd
httpd 1048930 apache txt REG 253,1 580064 53187782 /usr/sbin/httpd
httpd 1048931 apache txt REG 253,1 580064 53187782 /usr/sbin/httpd
httpd 1049032 apache txt REG 253,1 580064 53187782 /usr/sbin/httpd
httpd 1049033 apache txt REG 253,1 580064 53187782 /usr/sbin/httpd
httpd 1049411 apache txt REG 253,1 580064 53187782 /usr/sbin/httpd
(十六)查看連接到某個遠程主機端口的進程
哪些進程打開了到 www.dpqyw.com 的UDP 端口 8088(ntp) 的連接:
[root@htlwk0001host ~]# lsof -i UDP@www.dpqyw.com:8088
1
哪些進程打開了到 192.168.2.245 TCP 端口 1521 的連接:
[root@svr-db-test ~]# lsof -i tcp@192.168.2.245:1521 -n
1
lsof -n 不將IP轉換為hostname,缺省是不加上-n參數。
(十七)不斷查看遠程主機 ftp 連接的情況
[root@htlwk0001host ~]# lsof -i tcp@www.dpqyw.com:ftp -r -n
=======
=======
=======
1
2
3
4
說明:
-r,lsof 會永遠不斷的執行,直到收到中斷信號
+r,lsof 會一直執行,直到沒有檔案被顯示,缺省是 15s 刷新
-n 不將 IP 轉換為 hostname,缺省是不加上 -n 參數
(十八)遞歸查找某個目錄中所有打開的文件
[root@htlwk0001host ~]# lsof +D /usr/lib
1
加上+D 參數,lsof 會對指定目錄進行遞歸查找,注意這個參數要比 grep 版本慢:
[root@htlwk0001host ~]# lsof | grep '/usr/lib'
1
之所以慢是因為+D首先查找所有的文件,然后一次性輸出。
(十九)列出某個用戶打開的所有文件
[root@htlwk0001host ~]# lsof -u liaowenxiong
1
-u 選項限定只列出所有被用戶 liaowenxiong 打開的文件,你可以通過逗號指定多個用戶:
[root@htlwk0001host ~]# lsof -u liaowenxiong,liudehua
1
這條命令會列出 liaowenxiong 和 liudehua 用戶打開的所有文件。
你也可以像下面這樣使用多個 -u 做同樣的事情:
[root@htlwk0001host ~]# lsof -u liaowenxiong -u root
1
(二十)列出由某個用戶或某個進程打開的所有文件
[root@htlwk0001host ~]# lsof -u pkrumins -c apache
1
你可以組合使用多個選項,這些選項默認進行 或 關聯,也就是說上面的命令會輸出由用戶 pkrumins 或者進程 apache 打開的文件,若希望多個選項之間是 與 關聯,可用加上選項 -a。
(二十一)查看某個用戶的所有網絡連接
查看用戶 root 的所有網絡連接:
[root@htlwk0001host ~]# lsof -a -u root -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
NetworkMa 901 root 24u IPv4 22817 0t0 UDP htlwk0001host:bootpc->_gateway:bootps
nginx 26556 root 8u IPv4 137518 0t0 TCP *:http (LISTEN)
nginx 26556 root 9u IPv4 137519 0t0 TCP *:https (LISTEN)
nginx 26556 root 10u IPv6 137520 0t0 TCP *:https (LISTEN)
1
2
3
4
5
6
使用 -a 將 -u 和 -i 選項組合可以讓 lsof 列出某個用戶的所有網絡行為。
(二十二)列出所有內存映射文件
[root@htlwk0001host ~]# lsof -d mem
1
(二十三)列出所有加載在內存中並正在執行的進程
[root@htlwk0001host ~]# lsof -d txt
1
(二十四)查看使用網絡資源的進程 pid
[root@htlwk0001host ~]# lsof -t -i
1
-t 選項輸出進程的 PID,你可以將它和 -i 選項組合輸出使用某個端口的進程的 PID,如下:
[root@htlwk0001host ~]# lsof -t -i:3306
1050299
1050398
1064381
1
2
3
4
(二十五)殺掉所有使用網絡的進程
[root@htlwk0001host ~]# kill -9 'lsof -t -i'
1
(二十六)循環列出文件
[root@htlwk0001host ~]# lsof -r 1
1
-r 選項讓 lsof 可以循環列出文件直到被中斷,參數1 就是循環間隔時間是 1 秒,即循環周期是 1 秒,意思是每秒鍾重復打印一次,這個選項最好同某個范圍比較小的查詢組合使用,比如用來監測用戶的網絡活動:
[root@htlwk0001host ~]# lsof -r 1 -u john -i -a
1
(二十七)查看被打開的和網絡相關的文件
使用 -i 選項用來查看網絡相關的文件,其參數的格式如下:
lsof -i [46][protocol][@hostname|hostaddr][:service|port]
1
說明:
46 表示 IP 協議的版本
protocol 表示網絡協議的名稱,比如 TCP 或 UDP
hostname 或 hostaddr 表示主機域名或者主機 IP 地址
service 指 /etc/services 中的端口名稱,比如:smtp
port 表示端口號,可以指定一個或多個
-i 選項默認會同時輸出 IPv4 和 IPv6 打開的文件。
只列出 IPv4 或 IPv6 打開的文件:
[root@htlwk0001host ~]# lsof -i 4
[root@htlwk0001host ~]# lsof -i 6
1
2
列出占用一定端口范圍的所有的進程:
[root@htlwk0001host ~]#lsof -i TCP:1-1024
1
(二十八)統計系統打開的文件總數
[root@htlwk0001host ~]# lsof -P -n | wc -l
69360
1
2
命令中的 -P 選項表示不解析端口號,-n 選項表示不解析主機名,這兩個選項主要的目的是為了提升 lsof 命令的執行速度。wc -l 命令則用來統計 lsof 命令輸出的行數。
(二十九)殺掉屬於某個用戶的打開了文件的所有進程
[root@htlwk0001host ~]# kill -9 `lsof -t -u nick`
1
[root@htlwk0001host ~]# kill -9 $(lsof -t -u nick)
1
(三十)列出某個 IP 的網絡連接信息
[root@htlwk0001host ~]# lsof -i @47.114.59.256
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 1050299 root 72u IPv6 19473546 0t0 TCP htlwk0001host:36448->47.114.59.224:mysql (ESTABLISHED)
java 1050299 root 78u IPv6 19472650 0t0 TCP htlwk0001host:36488->47.114.59.224:mysql (ESTABLISHED)
java 1050299 root 79u IPv6 19473549 0t0 TCP htlwk0001host:36450->47.114.59.224:mysql (ESTABLISHED)
1
2
3
4
5
(三十一)同時列出連接某主機多個端口的網絡連接文件
列出目前連接主機 hadoop 的端口為:20,21,22,25,53,80 的所有文件信息,且每隔3秒不斷的執行 lsof 指令:
[root@htlwk0001host ~]# lsof -i @hadoop:20,21,22,25,53,80 -r 3
1
經典場景應用
(一)查看指定進程打開的特定文件(查看日志文件路徑)
場景描述:
同事今天請假了,但負責的 webserver 服務出現了問題,老板讓你看一下 webserver 服務的日志,但你不知道 webserver 服務的日志文件路徑,配置文件太復雜你不太懂,這時你可以執行以下命令查看日志文件路徑。
[devl@xungen ~]$ lsof -c webserver | grep -e 'log$'
webserver 10124 devl 4u REG 253,1 8814787 109523 /home/devl/application/webserver/log/webserver.00.log
1
2
(二)查看文件的內存映射路徑(查看已刪除文件的內容)
場景描述:
新來的同事誤刪除了 webserver 服務的日志文件,現在線上環境出現問題,需要查看 webserver 的日志,老板讓緊急處理一下,這時你只能通過日志文件的內存映射路徑來查看日志內容,那么怎么獲取文件的內存映射路徑呢?你要記住內存映射路徑的固定格式:/proc/進程ID/fd/句柄。接着你要知道 webserver 進程 ID 和日志文件的句柄,那么這時我們就可以使用命令 lsof,來查看進程ID和文件句柄了。
注意:文件句柄又叫文件描述符又叫文件號
[devl@xungen ~]$ lsof -c webserver | grep -e 'log$'
webserver 10124 devl 4u REG 253,1 8814787 109523 /home/devl/application/webserver/log/webserver.00.log
1
2
以上的執行結果顯示 webserver 服務的進程 ID 為 10124,日志文件句柄為 4u(即 4 號句柄),所以 /proc/10124/fd/4 就是日志文件(webserver.00.log)在 webserver 進程中的內存映射路徑,這時你用 tail 命令就可查看日志文件了。
[devl@xungen ~]$ tail -f /proc/10124/fd/4
[20190602 09:51:04|INF] start route ping process success
[20190602 09:51:04|INF] ping host[127.0.0.1:8888][3951] success
[20190602 09:51:09|INF] check session success
[20190602 09:51:09|INF] start route ping process success
[20190602 09:51:09|INF] ping host[127.0.0.1:8888][3596] success
[20190602 09:51:14|INF] start route ping process success
[20190602 09:51:14|INF] ping host[127.0.0.1:8888][3390] success
[20190602 09:51:19|INF] start route ping process success
[20190602 09:51:19|INF] ping host[127.0.0.1:8888][3383] success
[20190602 09:51:19|INF] check session success
擴展知識:
當進程打開了某個文件時,只要該進程保持打開該文件,即使將其刪除,它依然存在於磁盤中。這意味着,進程並不知道文件已經被刪除,它仍然可以向打開該文件時提供給它的文件描述符進行讀取和寫入。除了該進程之外,這個文件是不可見的,因為已經刪除了其相應的目錄索引節點。 在 /proc 目錄下存儲着反映內核和進程樹的各種文件。/proc 目錄掛載的是在內存中所映射的一塊區域,所以這些文件和目錄並不存在於磁盤中,因此當我們對這些文件進行讀取和寫入時,實際上是從內存中獲取相關信息。大多數與 lsof 相關的信息都存儲於以進程 ID 命名的目錄中,例如: /proc/1234 中存儲的是 PID 為 1234 的進程的信息。每個進程目錄中存儲着各種文件,它們可以使得應用程序簡單地了解進程的內存空間、文件描述符列表、指向磁盤上的文件的符號鏈接和其他系統信息。
(三)恢復被刪除的文件
當系統中的某個文件被意外地刪除了,只要這個時候系統中還有進程正在訪問該文件,那么我們就可以通過 lsof 從 /proc 目錄下恢復該文件的內容。 假如,由於誤操作將 /var/log/messages 文件刪除掉了,那么這時要將 /var/log/messages 文件恢復的方法如下:
首先使用 lsof 來查看當前是否有進程打開 /var/logmessages 文件,如下:
[root@htlwk0001host ~]# lsof |grep /var/log/messages
syslogd 1283 root 2w REG 3,3 5381017 1773647 /var/log/messages (deleted)
1
2
從上面的信息可以看到進程 syslogd(PID=1283)打開文件的文件描述符為 2w。同時還可以看到 /var/log/messages 已經標記被刪除了。因此我們可以在 /proc/1283/fd/2 中查看相應的信息,如下:
[root@htlwk0001host ~]# head -n 10 /proc/1283/fd/2
Aug 4 13:50:15 holmes86 syslogd 1.4.1: restart.
Aug 4 13:50:15 holmes86 kernel: klogd 1.4.1, log source = /proc/kmsg started.
Aug 4 13:50:15 holmes86 kernel: Linux version 2.6.22.1-8 (root@everestbuilder.linux-ren.org) (gcc version 4.2.0)
1 SMP Wed Jul 18 11:18:32 EDT 2007
Aug 4 13:50:15 holmes86 kernel: BIOS-provided physical RAM map:
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 0000000000000000 - 000000000009f000 (usable)
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 000000000009f000 - 00000000000a0000 (reserved)
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 0000000000100000 - 000000001f7d3800 (usable)
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 000000001f7d3800 - 0000000020000000 (reserved)
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 00000000e0000000 - 00000000f0007000 (reserved)
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 00000000f0008000 - 00000000f000c000 (reserved)
如果可以通過文件描述符查看相應的數據,那么就可以使用 I/O 重定向將其復制到文件中,命令語句如下:
[root@htlwk0001host ~]# cat /proc/1283/fd/2 > /var/log/messages
1
或者
[root@htlwk0001host ~]# sh -c 'cat /proc/1283/fd/2 > /var/log/messages'
1
然后修復文件的權限屬性並重啟 rsyslog 服務:
[root@htlwk0001host ~]# chown messages:adm /var/log/messages
[root@htlwk0001host ~]# systemctl restart rsyslog.service
1
2
這樣就完成了 /var/log/messages 文件的恢復工作。對於許多應用程序,尤其是日志文件和數據庫,這種恢復刪除文件的方法非常有用。
(四) 日志文件刪除后磁盤空間可用空間沒有變大,怎么解決
發現文件系統 /tmp 目錄下空間居然用滿了,但用 du 命令統計 /tmp 目錄中所有文件的大小,發現並沒有大文件,怎么回事呢?出現這樣的情況,很有可能是被刪除的大文件依舊有其它程序在使用,所以依舊占用着磁盤空間,只是我們正常的方式無法查看到此文件,換句話說就是文件沒有被徹底刪除,這時候我們可以使用命令 lsof 求證下 。
步驟 1:查看系統磁盤的使用情況
[root@htlwk0001host ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 8.6G 1.5G 6.7G 18% /
/dev/sda10 784G 325G 420G 44% /u01
/dev/sda5 8.7G 7.9G 407M 96% /tmp
/dev/sda2 15G 2.8G 11G 21% /usr
/dev/sda1 122M 12M 104M 10% /boot
tmpfs 7.9G 4.0K 7.9G 1% /dev/shm
1
2
3
4
5
6
7
8
如上所示,/tmp 可用空剩下 407M。
步驟 2:使用命令 lsof 查看正在被進程使用的與 /tmp 相關的文件
[root@htlwk0001host ~]# sudo lsof | grep /tmp
sleep 18833 peien.htg 1w REG 8,5 8321143673 54 /tmp/netstat.log (deleted)
netstat_2 13571 peien.htg 1w REG 8,5 8321143673 54 /tmp/netstat.log (deleted)
tcprstat 18823 root 2w REG 8,5 43632 49 /tmp/myrt.daemon.log
sh 18822 mysql 2w REG 8,5 43632 49 /tmp/myrt.daemon.log
sh 18822 mysql 1w REG 8,5 43632 49 /tmp/myrt.daemon.log
myrt.pl 26045 mysql 2w REG 8,5 43632 49 /tmp/myrt.daemon.log
myrt.pl 26045 mysql 1w REG 8,5 43632 49 /tmp/myrt.daemon.log
check_age 25298 mysql 2w REG 8,5 22049 33 /tmp/check_agent.log
check_age 25298 mysql 1w REG 8,5 22049 33 /tmp/check_agent.log
mysqld 3784 mysql 6u REG 8,5 15156 13 /tmp/ibH3IFN9 (deleted)
如上所示列表中的第二行,文件大小7個多G,文件標記已刪,但是依舊被進程“netstat_2”占用,該進程的 PID=13571。
步驟 3: 我們可以使用命令 ps 查看進程更為詳細的信息
[root@htlwk0001host ~]# ps -ef | grep 13571
51717 13571 1 0 2011 ? 00:15:00 /bin/bash /tmp/netstat_20110829.sh
51717 21456 13571 0 09:40 ? 00:00:00 sleep 10
zhuxu 21458 17014 0 09:40 pts/0 00:00:00 grep 13571
1
2
3
4
步驟 4:接着我們將此進程 kill 掉
[root@htlwk0001host ~]# sudo kill -9 13571
1
步驟 5:然后我們再看看那個已刪的文件是否被進程占用着
[root@htlwk0001host ~]# sudo lsof | grep /tmp
tcprstat 22084 root 2w REG 8,5 49339 49 /tmp/myrt.daemon.log
sh 22083 mysql 2w REG 8,5 49339 49 /tmp/myrt.daemon.log
sh 22083 mysql 1w REG 8,5 49339 49 /tmp/myrt.daemon.log
myrt.pl 26045 mysql 2w REG 8,5 49339 49 /tmp/myrt.daemon.log
myrt.pl 26045 mysql 1w REG 8,5 49339 49 /tmp/myrt.daemon.log
check_age 25298 mysql 2w REG 8,5 24583 33 /tmp/check_agent.log
check_age 25298 mysql 1w REG 8,5 24583 33 /tmp/check_agent.log
mysqld 3784 mysql 6u REG 8,5 15156 13 /tmp/ibH3IFN9 (deleted)
su 17013 root cwd DIR 8,5 4096 2 /tmp
sort 22090 zhuxu cwd DIR 8,5 4096 2 /tmp
如上所示結果,看不到那個已刪的大文件了。
步驟 6:我們再看看系統磁盤分區的使用情況,確認下 /tmp 的使用空間是否增加了
[root@htlwk0001host ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 8.6G 1.5G 6.7G 18% /
/dev/sda10 784G 325G 420G 44% /u01
/dev/sda5 8.7G 56M 8.2G 1% /tmp
/dev/sda2 15G 2.8G 11G 21% /usr
/dev/sda1 122M 12M 104M 10% /boot
tmpfs 7.9G 4.0K 7.9G 1% /dev/shm
如上所示,目錄 /tmp 的可用空間變成 8.2G 了。
————————————————
版權聲明:本文為CSDN博主「liaowenxiong」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/liaowenxiong/article/details/116002282
