Linux入門之進程管理(4)之進程與文件
前面使用進程相關命令管理工具都是根據進程編號或者進程名稱及其其它屬性信息來查看和處理相關進程的,但是在某些情況下,想要查看某個文件或者某個設備被哪些進程所使用,使用ps、pgrep等命令查詢的是不夠準確的,而且有些時候並不是簡單的去打開某個文本文件一樣,這樣還可以進行搜索過濾出來。而在linux系統中,除了常見的配置文件、日誌文件等文本文件,幾乎任何對象都會被內核映射去該有的文件,比如磁盤設備、掛載點等。當要知道那些用戶通過哪些進程來在訪問或者使用此文件時,就需要通過向文件的方式去查找其來鏈接的進程了。
linux軟件包中也提供了一些相關命令來解決:fuser lsof
fuser 命令
fuser - identify processes using files or sockets
通過文件或者套接字文件來識別器對應的進程
選項與參數:
fuser [-umv] [-k [i] [signal]] file/dir
-u:除了進程的PID之外,同時列出該進程的擁有者;
-m:後面接的那個文件名會主動的上提到該文件系統的最頂層,對於umount不成功很有效
-v:可以列出每個文件與進程還有指令的完整相關性;
-k:找出該文件/目錄的PID,並對與其PID對應的進程發送SIGKILL信號;
-i:必須與 -k 配合,在刪除PID 之前會先詢問使用者,交互式;
-signal:例如 -l -15 指定信號代碼,不指定默認爲SIGKILL(-9)信號。
使用案例:
1、顯示信息字段介紹
#找出對當前所在目錄的進行使用的進程的PID、所屬用戶、權限
[root@localhost ~]# fuser -uv . USER PID ACCESS COMMAND /root: root 13357 ..c.. (root)bash root 14154 ..c.. (root)bash
解析:這裏當前目錄在root家目錄,有兩個PID也就是兩個進程號分別爲13357、14154的進程在訪問此目錄,此進程所屬用戶爲root,並且進程指令爲bash。在ACCESS訪問的那一列有很多字符,下面一一介紹:
ACCESS:
c current directory. #當前所在此目錄
e executable being run. #已經運行的執行文件
f open file. f is omitted in default display mode. #被打開的文件
F open file for writing. F is omitted in default display mode.
#該文件被開啓,但是在等待迴應中
r root directory. #代表頂級目錄(root directory)
m mmap'ed file or shared library. #可能爲分享的動態函數庫
2、指定目錄或文件訪問進程列表查看
查看某個文件系統下有多少個進程正在佔用該文件,使用-m選項指定掛載點
#開啓另一個終端bash進程來備份當前關盤鏡像
[root@localhost ~]# dd if=/dev/cdrom of=/test/mk.iso
#回到剛纔終端查看/dev/cdrom設備
[root@localhost ~]# fuser -uv /dev/cdrom USER PID ACCESS COMMAND /dev/sr0: root 14756 f.... (root)dd
說明:f表示是一個被開啓的文件,因爲要讀取光盤數據,肯定是會打開訪問的。
#查看/proc虛擬文件系統掛載點又多少進程在訪問
[root@localhost ~]# fuser -muv /proc/ USER PID ACCESS COMMAND /proc: root kernel mount (root)/proc root 1 f.... (root)systemd root 2 ...e. (root)kthreadd root 3 ...e. (root)ksoftirqd/0 root 5 ...e. (root)kworker/0:0H root 7 ...e. (root)migration/0 root 8 ...e. (root)rcu_bh root 9 ...e. (root)rcuob/0
3、查看指定目錄訪問用戶及進程
查看所有使用到/home這個文件系統的進程
#使用另一個終端用hadoop並切換到用戶家目錄
[root@localhost ~]# su - hadoop [hadoop@localhost ~]$ whoami hadoop [hadoop@localhost ~]$ pwd /home/hadoop
#查看當前所在的bash進程
[hadoop@localhost ~]$ echo $$ 14803
#使用fuser 命令查詢出/home下訪問的進程指令及用戶和PID
[hadoop@localhost ~]$ fuser -muv .. USER PID ACCESS COMMAND /home: root kernel mount (root)/ hadoop 14803 .rce. (hadoop)bash
解析:這裏顯示了當前hadoop開啓的PID爲14803的bash進程,下面用pidof來確認。
#使用pidof確認當前所在會話進程
[hadoop@localhost ~]$ pidof -s bash 14803
說明:這裏的進程的發起者爲hadoop和其訪問目錄,/home本身爲/目錄的目錄,rce則表示此當前已經在此目錄中,並且正在打開使用中,因爲hadoop在/home/hadoop下,當然已經進入了,且爲頂級目錄。
4、掛載點目錄的強制卸載
當有時候因爲有內存中大量的數據尚未寫入到文件系統的掛載點中,但是又想要卸載此掛載點,這時就可以用到-k和-m選項來指導掛載點並強制停止掛載點的使用。
#查詢新建的/dev/sda3分區的掛載點爲/test目錄
[root@localhost ~]# findmnt /dev/sda3 TARGET SOURCE FSTYPE OPTIONS /test /dev/sda3 ext4 rw,relatime,seclabel,data=ordered
#下面對此目錄進行大連讀寫操作
[root@localhost ~]# tar -jcf /test/iso.bak /mnt/Packages/* &
#確定此進程仍在後臺運行
[root@localhost ~]# jobs [1]+ Running tar -jcf /test/iso.bak /mnt/Packages/* &
#使用umount卸載/test掛載點
[root@localhost ~]# umount /test/ umount: /test: target is busy. (In some cases useful info about processes that use the device is found by lsof(8) or fuser(1))
說明:這裏閒了了target is busy表示此掛載點目錄正在被使用中,所以無法卸載,在以往可以使用pkill、pgrep等命令來查看tar相關進程並進行kill -9來強制殺掉此進程,但是如果使用pkill或者pgrep的-f選項來完整過濾命令行是很難精確匹配的,如果在多個終端上都有此訪問,可能會誤殺。
#因此使用fuser直接找到對應的文件目錄的進程PID
[root@localhost ~]# fuser -muv /test/ USER PID ACCESS COMMAND /test: root kernel mount (root)/test root 14877 F.... (root)bzip2
說明:這裏顯示了F說明此目錄並每人進入範圍而是後臺對其操作。並且顯示的確定命令居然顯示不是tar命令,而是bzip2命令,這就更好解釋了,因爲tar -j命令就是調用bzip2命令進行對歸檔文件的壓縮。對此可以判斷通過這裏可以看到最直接的命令調用。
#使用-k默認發送-9信號,-m將/test目錄排隊到文件系統映射的最前面,這樣殺死對目錄有訪問有關的所有進程都會殺死。
[root@localhost ~]# fuser -km /test /test: 14877
#再次查看/test目錄下的進程,只有最基本的系統內核的文件系統了
[root@localhost ~]# fuser -muv /test/ USER PID ACCESS COMMAND /test: root kernel mount (root)/test
#下面直接卸載,沒有提示錯誤或警告
[root@localhost ~]# umount /test
#再次查看當前掛載點中,通過與運算符判斷輸出,已經被卸載掉了
[root@localhost ~]# mount | grep '\</test/\>' && echo 'mountpoint such' || echo 'mountpoint no such' mountpoint no such
lsof 命令
lsof - list open files
與fuser查看文件的相關進程信息相反,此命令是通過進程來列出對應進程所在使用的文件。
選項與參數:
lsof [-aUn] [+d]
-a:多項數據需要同時成立才顯示出結果,類似find中-a的作用;
-U:僅列出unix like 相關的 socket 文件類型;
-uuname:列出指定進程的生效者所開啓的文件;
+ddirpath:找出指定目錄下已經被開啓的文件;
使用案例:
#列出當前系統上面所有被開啓的文件
[root@localhost ~]# lsof
說明:這裏的信息與ps直接列出的信息有些相識,只是CMMADN列爲直接調用的命令名,而
NAME則表示了被開啓的文件的完整路徑。DEVICE列還顯示了對應的文件所在文件系統的主設備號和此設備號。USER顯示了使用的用戶,TYPE顯示了此文件的類型。還有NODE此列表示文件對應的indoe編號。
#累出關於root的所有進程開啓的socket文件
[root@localhost ~]# lsof -u root -a -U
解析:因爲套接字爲進程間通信時臨時產生,所有爲內存中的臨時文件,這裏的DEVICE表示了每個套接字文件對應的其唯一的標識符號。
#列出所有系統上列出的被啓動的周邊裝載
[root@localhost ~]# lsof +d /dev
#配合grep過濾出只屬於root用戶咋在bash進程所開啓的文件
[root@localhost ~]# lsof -u root | grep '\<bash\>'