大概在十多年前,我當時還是一個產品經理。由於一些工作的原因,需要向運維工程師學習一些linux常用命令。
當使用linux ps這個十分常用的命令時,遇到了一個小小的疑惑。有些工程師推薦使用ps aux的命令組合,有些工程師推薦使用ps -aux的命令組合,從輸出結果上來看似乎也沒有什麼不同。
考慮到如常用的ls -l命令在內,很多linux命令選項前都要加上一個短橫線,這麼來看似乎ps -axu是正確的。
但是一些早期的linux版本,在執行ps -axu時又會報出如下錯誤Warning: bad syntax,而ps aux卻沒有這樣的報錯信息,這麼看來似乎ps aux又是正確的。查閱市面上的一些linux書籍,在介紹linux ps命令示例時,有些說用ps aux,而有些又說用ps -axu。實在是讓我這個初學者摸不著頭腦。
再後來,隨著我加入運維團隊對linux ps命令逐步深入使用,學會了查看man page和help,發現其中有ps命令的exmaple,果然是ps aux的用法是正確的。
不過隨著對linux ps命令使用的逐步深入,對ps命令的其他疑問越來越多。比如,我們天天在使用ps命令時輸出的%CPU列到底是什麼含義?為什麼和top顯示的%CPU的值有時候差異非常大?
再比如,當我使用ps -el命令時,為什麼我的進程名是systemd-journald,而ps命令只顯示systemd-journal,弄丟了最後1個字母d。
帶著這麼多疑惑,3年多前我有機會簡單的學習了一下linux ps原始碼,逐步解開了上面這些疑惑。後來發現公司的很多同事也對ps命令有各種問題和疑問,於是想把之前對ps命令的學習經驗總結成文檔,供大家參考。希望能給大家帶來幫助。
二、Linux ps命令選項解析Linux ps命令功能很強大,了解ps命令首先需要從ps命令的選項格式入手。像其他很多linux shell命令一樣,ps命令的選項也有長格式和短格式的區別。短選項中也可以帶中橫線、也可以不帶中橫線。
根據選項長短和是否有橫線的情況,ps命令的選項可以分為以下3類:
BSD風格語法,必須不能以中橫線開頭;
SYSV風格語法,必須僅一個中橫線開頭;
GNU風格語法,必須以兩個中橫線開頭;
不過linux ps命令的長選項並不多,而且幾乎每個長選項都有一個功能完全相同的短選項對應。在centos7環境運行如下命令可以見。
在本文中我們將主要介紹BSD和SYSV兩種風格的ps命令選項。如果大家有對GNU風格的長選項使用的需求,那麼可以參考對應的短選項語法即可。需要注意的是GNU風格選項都是帶參數值的,例如—sid 1。
各風格的ps命令選項可以混合使用,比如:
Linux ps命令解析SYSV和BSD風格選項時,會分別將每組字符串都解析成單獨的字母。以下三個實例,拆分前後的命令都是等價的。
從示例中可以看出,當SYSV風格語法一個中橫線之後有多個字母選項時,拆分後需要給每一個字母前都加上一個中橫線。也就是說-elL轉換為-e -l -L,而不是轉換為-e l L。
從上面例子中也可以看出,ps命令選項除了有是否加中橫線的區別,字母大小寫也表現為不同的選項含義。英文字母一共26個,SYSV風格選項-A到-Z和-a到-z共52個,BSD風格選項A到Z和a到z共52個。於是ps命令就有一共104個命令選項可能性。
不同版本的ps命令選項的使用可能略有出入,本文主要使用主流的centos7上的procps-ng version 3.3.10版本來說明。
在這104個命令選項中,未啟用的或曾經使用過現在廢棄的命令選項有如下40個,分別是A、B、C、D、E、F、G、I、J、K、P、Q、R、W、Y、b、d、i、y、z、-B、-D、-E、-I、-J、-K、-Q、-R、-S、-W、-X、-Y、-b、-h、-i、-k、-r、-v、-x和-z。
既然是未啟用或已廢棄,那麼運行帶這個選項的ps命令應該會報錯。試運行下大部分確實如此,不過也有幾個例外,比如ps -x命令就不報錯,可以正常輸出。這樣的例外選項一共有如下7個-S、-X、-h、-k、-r、-v和-x,本文第九節會給予說明。
這104個命令選項中的其餘64個選項就構成了linux ps命令的龐大命令選項體系,接下的內容就對他們分別給予介紹。
要查看我們當前ps命令的版本,就用到V、-V這2個選項。
為了本文中意思表達更加準確,這裡借用資料庫中的幾個概念。ps命令輸出結果,約定為結果集。結果集中的每一行,我們約定為記錄(record)。結果集或記錄中的每一列,我們約定為欄位(field)。
三、Linux ps命令的記錄類選項差不多每一個工程師使用ps命令時應該都有這樣的疑問, 使用ps aux時輸出結果中記錄行數要遠大於只使用ps命令時(如下所示)。
這其實會讓很多工程師在使用ps命令查找需要的進程時心裡很忐忑,會不會由於命令的選項使用不當導致ps沒有列出所需要的進程信息。正是這個原因,我們首先需要搞懂ps命令影響記錄行數的那些選項。
3.1、all_processes選項Linux ps命令的記錄類選項大概有20幾個之多。有些可以列出所有的進程信息,有些按某種規則篩選顯示部分進程信息。如今作業系統中awk、sed和grep這些shell文本處理命令的功能都十分強大,我們重點還是掌握ps命令中那些顯示所有進程信息記錄的選項,其他ps命令過濾選項都可以通過shell文本處理命令(awk、sed和grep)間接實現。
Linux ps命令顯示所有進程信息的選項只有2個,即SYSV風格的-e和-A。相比之下,-e更容易記憶和書寫,請大家牢記這個-e選項。
大家知道,ps命令的所有信息都是linux kernel生成,並通過/proc/目錄輸出給用戶空間的。在/proc/目錄下,每一個以數字開頭的目錄,就對應一個進程信息。既然如此,通過如下命令便可一目了然。
參數-e和-A顯示的進程記錄數確實和proc目錄下的所有進程目錄數一致。
3.2、simple_select選項Linux ps命令的simple_select選項一共5個,具體包括-a、-d、a、g和x。他們包括2個SYSV風格和3個BSD風格選項。2個SYSV風格和3個BSD風格的選項不能同時使用,否則會報錯。
2個SYSV風格或3個BSD風格內部可以組合使用,具體的組合可能性有-ad、ga、ax、gx、agx。這裡值得注意的是這種字母組合選項絕對不是單字母選項篩選規則的簡單組合,ps命令給這幾種組合賦予了新的篩選規則。
Linux環境下的ps命令,會對BSD風格simple_select選項部分做2個特殊處理:
按照這2個特殊處理規則,ps aux選項組合等價於ps auxg,等價於ps agx u,等價於ps -e u。
總結下來,ps命令simple_select選項只有6種組合情況-a、-d、-ad、g、ga、gx。每一種選項都賦予一個位圖值。ps命令通過位圖計算來實現它的篩選規則。比如g選項的位圖值select_bits是0x0a0a,下面以g選項為例說明。
關於8、4、2、1的含義(關於tty、session、tgid和euid欄位含義參考第七節):
很明顯「4」這位都缺失,1這位都存在,那麼g選項的含義就是:顯示所有tty值存在的且euid值等於當前進程euid值的進程。對此持懷疑態度的同學可以通過如下2個命令進行驗證。
同樣的分析方法,其他幾個選項和選項組合的含義:
選項-a含義:顯示所有tty值存在的且session值不等於當前進程tgid(pid)值的進程;
選項-d含義:顯示所有session值不等於當前進程tgid(pid)值的進程;
選項組合-ad含義:顯示所有tty值存在的或session值不等於當前進程tgid(pid)值的進程。換句話說,被過濾掉的是所有tty值為空的且session值等於當前進程tgid(pid)值的進程;
選項組合ga(或選項a)含義:顯示所有tty值存在的進程;
選項組合gx(或選項x)含義:顯示所有euid值等於當前進程euid值的進程;
3.3、selection_list選項這類選項比較容易理解,都是根據進程的某個屬性值對進程進行篩選。他們大多需要一個選項的參數,而且也都有功能完全一樣的GNU風格的長選項對應。此類選項一共13個,主要分為如下幾組:
這些選項不但可以單獨使用,還可以組合使用(如下所示)。需要注意的是這些選項之間的組合是邏輯或的關係,即或者符合-u選項條件或者符合-p選項條件。
$ ps -u root -p 1
3.4、特殊選擇選項$ ps -e r
本節前幾部分全面的介紹了記錄篩選類選項,本小節將對這些選項的綜合作用順序進行一個系統介紹。
記錄類選項是對/proc/目錄下的進程信息逐條篩選過濾的:
首先判斷是否有all_processes選項。如果有all_processes選項,則本條記錄被選擇。如果沒有all_processes選項,則繼續下一規則。
其次判斷是否有simple_select選項。如果有simple_select選項,則使用simple_select選項規則判斷本條記錄是否被選中。如果沒有被simple_select選項選擇,則繼續下一條規則。
然後判斷是否有selection_list選項。如果有selection_list選項,則使用selection_list選項判斷本條記錄是否被選中。如果沒有selection_list選項,則繼續下一條規則。
然後判斷選項中是否有BSD風格的選項。如果有BSD風格選項,則使用simple_select類的選項g規則判斷本條記錄是否被選中。如果沒有BSD風格選項,則進入下一條規則。
此時不論ps命令有SYSV風格選項還是僅無選項ps命令,都會使用一個新的simple_select選項位圖進行篩選過濾,位圖值為0xaa00。如果還沒有被選中,則徹底失去被選中的機會。位圖值0xaa00的意義是:所有tty值等於當前進程tty的且euid值等於當前進程euid值的進程。
接下來再看是否有r選項。如果有r選項則以上5個環節被選中的記錄中,只有R和D狀態的記錄才能被繼續選中。如果沒有r選項,則以上5個環節中被選中的記錄,都繼續被選中。
最後看是否有-N選項,如果有-N選項則以上第6個環節選中的將不被選中,第6個環節未選中的將被選中。如果沒有-N選項,則以上第6個環節中被選中的記錄,還繼續被選中。
選項h單獨生效,如果有h選項則取消結果集的標題欄,如果沒有h選項則標題欄保持輸出。
四、Linux ps命令輸出結果排序選項上面一章介紹了記錄類選項的使用,了解了如何篩選符合我們要求的記錄集。如果我們需要對輸出結果進行排序,那麼ps命令也給我們提供了3個選項,分別是k、f和-H。
4.1、欄位排序選項選項k可以讓我們以某個欄位為條件對輸出結果進行排序,並且還可以使用+-符號設置升序排序還是降序排序。
選項k還可以使用多個欄位同時對結果集排序,從輸出結果可以看到,先按ppid進行升序排序,ppid值相同時,再按rss值進行升序排序。
4.2、樹形排序選項每一個進程都有一個父進程,所有用戶空間的進程的最終父進程都是1號進程,所有內核空間的線程的最終父線程都是2號線程。這樣所有進程按照父子進程的關係就可以構成2個樹形結構。選項f和-H就是實現這個樹形排序功能的2個選項。
從上面的結果中不難看出,選項f是使用ACSII碼對父子進程進行關聯,選項-H是使用tab空格對父子進程進行關聯。
五、Linux ps命令線程展開選項前面章節主要是說明了如何篩選和顯示進程的信息。同一個進程有時候還會起多個線程,同樣內核也在/proc/目錄下顯示了進程的線程信息,如下所示。
Linux ps同樣提供了一組選項可以將每個進程的線程信息詳細展現,這組選項包括H、-L、-T、M、m和-m。在講解這些選項之前,我們先看一個小測試。
同樣為了統計的準確,用h選項去掉標題欄信息。其中最後一個486的值是ps -e h的記錄數,說明當前系統有486個進程。非常巧的是486恰巧等於1217減去731的值。從這裡我們可以了解到H、-L和-T這3個選項記錄數都是731,M、m和-m三個選項記錄數都是1217。找一個起了多線程的進程查看下具體輸出內容。
選項-L的輸出可以看到一共4行輸出結果,第一行PID等於LWP(線程ID)的值,說明是線程組的主線程(即進程)。其餘三個線程ID各不相同,但PID值都和主線程的PID值一樣,說明是同一線程組的普通線程。
第二組三個選項單純的顯示不便識別,我們這裡先引入一個後面講解的O選項,額外增加一個輸出值LWP。
可以看到一共5行輸出結果,對照上面的輸出我們可以判斷出,第二組選項除了把線程組中的4個線程分別顯示之外,又額外增加了一行內容專門用於顯示這個線程組(即進程)的信息。我們再回頭看前面的1271減去731等於486應該就很容易明白了。
在H、-L和-T之間,以及M、m和-m之間,輸出信息也略有不同,不過這些都是數據項和格式的不同,後面有專門章節介紹。
六、Linux ps命令的欄位選項6.1、欄位組合類通用選項很多人在使用ps命令時都會注意到,在我們輸入不同的命令組合時,ps命令輸出結果中列的數據項並不統一。比如下面2個命令。
Linux ps命令的aux選項組合輸出PID、%CPU、%MEM、RSS、TIME等數據項,ps命令的-el選項組合輸出PID、PPID、WCHAN、TIME、CMD等數據項。首先一個問題就是,ps命令一共有多少數據項可以輸出。這個問題很好回答,通過L選項很容易獲取,一共有168個數據輸出項。
其次的一個問題就是,是什麼決定了ps aux命令輸出結果中恰恰包含USER、PID、%CPU、%MEM、VSZ、RSS、TTY、STAT、START、TIME和COMMAND這11個數據項呢。原因是ps命令中有一些選項用來對數據欄位進行固定組合的作用。其中aux中的u選項就固定包含了以上11個數據輸出項,並且他們的顯示順序也已經固化在代碼中。
Linux ps命令這種欄位組合類選項一共15個。其中6個選項用途比較廣泛,其餘9個選項都主要適合在查詢某一種問題時使用。
本小節先介紹6個通用選項:
採用詳細格式顯示進程狀況,此類選項所顯示欄位主要為一些常用欄位信息。
6.2、欄位組合類專用選項本小節先介紹9個適合特殊用途的專用選項:
也許有人已經觀察到了,以上欄位組合選項,不論哪個都會固定的有幾個欄位總是出現,比如PID、TTY、TIME和CMD等。下面請大家先看一下這幾個例子。
從以上例子中,我們可以得出幾個信息。參數為BSD風格時,默認都會顯示PID、TTY、STAT、TIME和COMMAND這5個欄位。參數為SYSV風格時,默認都會顯示PID、TTY、TIME和CMD這4個欄位。ps命令無參數時默認為SYSV風格。
6.3、自定義欄位選項上一小節欄位組合選項是ps命令為了一些常用場景固化在代碼中的固定數據項組合。但是如果以上所有組合都不滿足我們的要求,或者我們為了提升ps命令運行效率僅僅需要個別的數據項輸出。那麼我們可以通過-o或o選項來實現自定義數據項的輸出功能。比如我們對ps j這個命令欄位組合的輸出信息不滿意,我們自定義他的輸出。
前文提到過,ps命令一共可以輸出168個欄位,ps L命令可以顯示這168個欄位的詳細情況。第一列小寫字母是-o選項的參數,可以通過逗號隔開。第二列大寫字母是ps命令輸出的結果集標題欄名稱。
儘管大部分情況下-o參數和標題欄都僅僅是大小寫的轉換關係,但也有不那麼完美的時候,以進程的執行命令欄位為例。
這個例子至少可以說明兩點,不同的說明符(specifier,-o選項參數)可能輸出同樣的標題欄。儘管標題欄一樣,但顯示的內容可能是有區別的。
有些說明符還提供縮寫,下表是ps命令有縮寫的說明符和縮寫的對應關係表,一共15個。
有了說明符的縮寫之後,可以對自定義欄位的輸出欄位之間添加自定義分隔符。區別於以往ps命令各輸出欄位都是使用空格作為分割,使用自定義分隔符之後將更方便使用shell數據處理命令進行解析。
前文提到所有欄位組合選項都默認包含4個或5欄位。如果想在自定義欄位組合時也默認添加一些常用欄位,而同時又省去-o選項參數的輸入過程,那麼可以使用O或-O選項。
這2個選項O或-O,會在自定義欄位之前默認增加pid欄位,在自定義欄位之後默認增加state、tname、time和command欄位。
七、Linux ps命令欄位修飾選項本節前面的選項都是決定輸出結果中欄位的數量和順序,本小節將介紹幾個只對輸出結果中某個欄位進行修飾的選項。首先來看-w和w選項。
這個實例說明,當屏幕不是很寬時,如果進程命令很長,默認情況下,會將命令超出屏幕的部分截取掉,這樣勢必會影響系統管理員調查問題,使用w或-w選項,就會將完整的進程命令信息顯示,多出的部分換行顯示。有的時候為了效果好一點,建議我們可以多使用幾次w選項,比如ww、www或wwww。
接下來我們再來看一下c和e選項。
選項u的COMMAND欄位,默認會輸出進程路徑和執行參數信息。從上面的例子可以看出,選項c可以使選項u的COMMAND欄位更加精簡,只保留進程名稱。選項e可以使選項u的COMMAND欄位更加豐富,增加進程環境變量的相關內容。
當選項S被選中,ps命令在顯示如下6個欄位信息時,會將已經死亡的子進程信息也包含計算在內,如果未選中S選項將不會計算這些已經死亡的子進程信息 。快速同時執行如下2個命令,即可看出這6個欄位值,選中S值後比之前有明顯增大。具體欄位含義請參考8.5小節和8.6小節。
Linux ps命令的欄位中有個wchan欄位(wchan相關含義參考8.8小節)。默認情況下ps命令會輸出wchan的符號信息,如果希望輸出wchan的原始數值信息,可以使用n選項。請比較如下2個命令,添加n選項前後第11個欄位的輸出差別。除了wchan之外,選項n還可以將原本輸出user name的地方轉換為user id輸出。
欄位wchan的數值信息和符號信息的映射關係通過作業系統中一些System.map文件完成,如果用戶需要使用自定義的System.map文件,可以通過選項N或-n完成,如下示例。
八、Linux ps命令常用欄位前文提到linux ps一共最多可以輸出168個欄位,通過ps L命令可獲取詳情。通過欄位相關選項可以獲取符合用途的欄位組合。為了讓大家對ps命令的理解更加深入,本節會深入介紹一些常用的輸出欄位的含義。
按照這些常用欄位的內在關係,我們將分為以下八個小結介紹。
8.1、進程ID類欄位進程ID類欄位是ps命令欄位中最基礎的一類。為了能更加形象的說明這些ID的關係和含義,請大家按照如下命令順序操作。
對以上輸出結果的欄位逐條說明:
欄位tid表示進程的線程ID,可以看出每個線程的tid都不相同。
欄位nlwp表示當前線程組中的線程個數,以上命令都是單線程進程,因此此值均為1。
欄位pid表示進程ID,也可以看出每個進程的PID都不相同。
欄位pgid表示進程組ID,上面的例子中除了和setsid結合的vmstat命令,其餘三組通過shell管道連接起來的命令的pgid都相同。比如tail、awk和nl命令的- pgid都為1384,且pgid值為組內第一個命令tail的pid值;iostat、sed和fold命令的pgid都為1388,且pgid值為組內第一個命令iostat的pid值。
欄位sid表示會話ID。上面的例子中最後一行是第三個登錄終端的shell。第一個登錄終端上的所有進程sid都相同,且為登錄shell的pid值1351;除了和set- sid結合的vmstat命令,第二個終端上的所有進程sid都相同,且為登錄shell的pid值1394。
欄位tpgid表示進程連接到的tty(終端)所在的前臺進程組的ID。除了vmstat進程之外,第二個終端上的所有進程tpgid也都等於登錄shell的pid值1394。但是第一個終端上的所有進程tpgid卻都等於第一個終端上又啟動的那個shell的進程id值1370。充分說明了tpgid值是連結著終端的前臺進程組ID值。
欄位ppid表示父進程ID。
最後我們再來解釋和vmstat結合的setsid,setsid就是使和它結合的vmstat脫離原來的會話,脫離之後pgid和sid都等於了vmstat進程的pid,同時父進程也由1號進程託管。此時也沒有了所依附的終端,tpgid統一等於-1。Linux上的所有守護進程的tpgid值都是-1。
進程ID類欄位的別名情況:欄位spid和欄位lwp是欄位tid的別名,欄位tgid是欄位pid的別名,欄位pgrp是欄位pgid的別名,欄位sess和欄位session是欄位sid的別名。
8.2、命令名欄位命令名相關的欄位一共有3組,如下所示。
命令名欄位的別名情況:欄位comm和欄位ucomm是欄位ucmd的別名,欄位args和欄位command是欄位cmd的別名。
建議大家掌握ucmd和cmd這2個欄位,cmd為長命令名欄位,ucmd為短命令名欄位,可以理解為unadorned cmd(未加修飾的命令名)。
前文提到過如果程序名稱長度超過15位,ps命令的短命令名無法完整顯示16位及以上的部分。下面看一個小例子來說明這個問題。
從上面的例子可以看出,當程序名稱超過15位時,確實短命令名無法顯示完整的程序名稱,只顯示了15位。進一步查看/proc/8040/目錄,可以發現如下信息。
查詢內核代碼,可以發現comm值取自內核struct task_struct結構體的comm屬性欄位。
這就告訴我們通過ps命令短命令欄位無論如何都無法輸入超過15位的程序名稱,原因是內核數據結構原生就只支持15個字符長度的程序名稱。
除此之外上面的例子還給我們另外一個啟示,如果通過使用SYSV風格的短命令名就可以滿足使用要求(如ps -el),那就儘量不要使用BSD風格的長命令名(如ps -e u,即ps aux)。長命令名需要依賴內核中健康的文件系統,而當文件系統工作不正常時,往往短命令名卻可以不受影響。所以我們在實際生產中偶爾會發現系統中有大量ps aux進程D住的情況。
8.3、進程狀態欄位進程狀態類欄位一共有三個,分別是s、state和stat,如下所示。
欄位s和state互為別名,值為單字節進程狀態。這裡重點介紹一下stat選項的多字節進程狀態,查看一下ps命令關於這個多字節進程狀態的c語言代碼。
根據以上原始碼,我們來逐條解釋:
字符』<』表示nice值小於0,nice值最小為-20。進程特性nice值允許進程間接的影響內核調度算法。所謂nice就是指對其他進程的謙讓程度,顯然比0越小就越不謙讓,比0越大就越謙讓。顧名思義,越謙讓的君子在CPU調度過程中佔用CPU的時間會越少,反之不謙讓的進程相比較可能佔用更多的CPU時間。因此字符』<』表示此進程可能在調度過程中獲得優勢。
字符』N』表示nice值大於0,nice值最大為19。因此字符』N』表示此進程可能在調度過程中不能獲得優勢。
字符』L』表示進程vm_lock值為真,即此進程有內存頁被鎖在內存中,這些內存頁不能通過換頁換出。
字符’s』表示進程的tgid(pid)值等於進程的session(sid)值,這說明當前進程是會話的leader,參考8.1小節。
字符』l』表示進程中的線程數量大於1,這說明當前進程是一個多線程程序。
字符』+』表示進程的pgrp(pgid)值等於進程的tpgid前臺進程組ID,這表示當前進程在前臺進程組中。
8.4、時鐘(系統)時間類欄位時鐘時間(系統時間)類欄位,記錄了進程開始時間點和執行的時長信息,這類欄位一共有6組。其中4個記錄進程開始時間點,2個記錄進程執行時長信息,示例如下。
從自動化運維腳本的角度,lstart欄位的輸出信息格式更加規範便於解析,etimes欄位作為一個正整數也可以直接使用。欄位start_time是欄位stime的別名。下面給一個使用的例子。
欄位lstart的輸出固定佔用了2 2 6這5列信息,這樣在其後的etimes欄位也固定佔用了第$7列。使用awk結合date命令很方便的就將進程開始時間轉化為時間戳格式。
8.5、CPU時間和使用率欄位CPU時間和使用率類欄位一共有5組,記錄了進程所消耗的CPU時間片和CPU使用率信息,示例如下。
欄位bsdtime的輸出相比較cputime更加方便轉換為正整數的秒數。欄位cp的單位是千分比,不能超過999。欄位c是百分比,不能超過99。
進程CPU時間類欄位別名:欄位atime和欄位time是欄位cputime的別名;欄位util是欄位c的別名;欄位%cpu是欄位pcpu的別名,但是%字符在crontab中使用並不友好,推薦使用pcpu。
下面來說明一下ps命令的CPU利用率的含義,先運行一個例子。
從這個命令運行的結果可以看出bsdtime除以etimes的值轉換為百分比後,基本和pcpu的值相等。這就足以說明ps命令的CPU利用率欄位指標是指從進程開始運行以來進程所耗費的CPU時間片佔時鐘時間的百分比。有時候這個值大於100%,那是因為進程啟用了多線程,很多時候有多核在同時使用CPU時間片。
看過top命令源碼可以知道,top命令默認是取最近3秒鐘進程所耗費的CPU時間片除以3秒鐘的百分比值。我們可以設想一種場景,如果一個進程已經運行了1年以上,平時都很穩定。
但是剛剛就在十幾分鐘前突然運行大量線程,佔用大量CPU資源。結果你在你剛剛登陸系統之前10秒鐘這些運行的線程都結束了。那麼你不論是通過top命令的CPU利用率指標,還是ps命令的CPU利用率指標都無法發現剛才作怪的這個線程的跡象。
8.6、進程內存相關欄位進程內存相關欄位也ps命令欄位中非常重要的一類,主要分為如下9組,示例如下。
對以上輸出結果的欄位逐條說明:
欄位vsz(virtual memory size)表示進程所申請的虛擬地址空間的內存大小,單位KB。在64位系統中,每個進程都有128Tb大小的堆內存虛擬地址空間的內存空間大小。vsz值並不反映進程佔用的真正物理內存大小。
欄位rss(resident set size)表示進程真正佔用了的物理內存大小,單位KB。
欄位pmem表示進程佔用的物理內存大小(rss)佔本機總物理內存大小百分比。
欄位trs(text resident set size)表示用於可執行代碼的物理內存大小,約等於進程的程序尺寸大小。
欄位drs(data resident set size)表示可執行代碼之外的內存大小,實際基本等於vsz減去trs的值。
欄位size表示如果進程交換到磁碟所需的交換空間大小。
欄位sz表示進程在物理頁面中的核心鏡像的大小。
欄位minflt表示此進程中發生的次缺頁異常的數量,下面詳細介紹。
欄位majflt表示此進程中發生的主缺頁異常的數量。
進程內存相關欄位別名:欄位m_drs和欄位dsiz是欄位drs的別名,欄位vsize是欄位vsz的別名,欄位m_size是欄位sz的別名,欄位rssize、欄位rsz和欄位sgi_rss是欄位rss的別名,欄位m_trs、欄位trss和欄位tsiz是欄位trs的別名,欄位%mem是欄位pmem的別名,欄位min_flt是欄位minflt的別名,欄位maj_flt和欄位pagein是欄位majflt的別名。
下面通過一個例子來加深對缺頁異常的理解。
可以看出欄位rss和欄位minflt的比值趨近於4。作業系統管理內存的基本單元是4096位元組大小的頁框,當進程訪問尚未有物理內存建立頁表映射關係的虛擬內存地址值時,會產生一次缺頁異常。在缺頁異常處理過程中會為虛擬內存頁分配一個物理內存頁並建立映射。
所以每一次缺頁異常就會分配4096(4kb)字節的物理內存,這樣rss和minflt的比值當然就是4了。如果分配之後又有釋放,後面再次分配,會使這個比值逐步小於4。如果這個比值過於小,那我們就有充足理由懷疑用戶程序代碼在內存管理上存在重大問題。
8.7、進程憑證類欄位進程憑證類欄位一共有30多個,其中大部分可以匯總為如下表格。
其中有些憑證是另外憑證的別名,比如uid是euid的別名,svuid是suid的別名,fsuid是fuid的別名。因此這些憑證欄位簡單的可以歸納為如下4方面憑證:
實際憑證 (real user ID):一般表示進程的創建者,屬於哪個用戶創建。
有效憑證 (effective user ID):表示進程對於文件和資源的訪問權限,具備等同於哪個用戶的權限。
保護憑證 (saved set-user-ID):set-user-ID的保存ID。
文件系統憑證 (file-system user ID):已經基本廢棄。
8.8、WCHAN欄位WCHAN類欄位一共3個nwchan、wchan和wname。WCHAN就是waiting channel的意思,進程正在休眠的內核函數的函數符號名稱。R狀態進程此欄位值為「-」。
欄位wchan和wname都顯示的是內核函數的函數符號名稱信息,默認只顯示6個字節。如果希望顯示完整的函數名稱,可以通過在欄位名稱後加冒號再加寬度數值的方式顯示更豐富信息,即wchan:25。
欄位nwchan顯示的是內核函數符號的指針地址數值信息。一個完整的64位的內核函數指針地址是一個16位的十六進位值,前10位固定為』ffffffff81』,因此ps命令的nwchan欄位只顯示出了後6位的十六進位值。
比如指針地址是ffffffff8124bb7e,那麼nwchan顯示24bb7e。如果後6位的高位有0,則省略掉0的顯示。
九、Linux ps命令選項容錯機制Linux ps命令所有的選項和大多數欄位都解釋過了,現在該說說文章開頭那個報錯的ps -axu了。
ps命令會提供一種選項容錯機制。當用戶輸入的是一個SYSV風格參數組合後,如果參數解析失敗,ps命令會繼續嘗試把同樣的字母組合都轉換為BSD風格再嘗試進行一次解析。
比如ps -aux解析失敗後嘗試按ps aux解析,ps -x解析失敗後嘗試按ps x解析。當然了,如果再次按照BSD風格嘗試解析仍失敗,那ps命令會最終失敗報錯。
事實上,能有機會被ps命令容錯機制糾正的錯誤選項只有這7個,-S、-X、-h、-k、-v、-r和-x。因為這些字母雖然沒有SYSV風格的選項,但是卻都有BSD風格的選項。
最後說一下,沒有將BSD風格到SYSV風格的容錯機制,比如SYSV風格有-F選項,而BSD風格沒有F選項。運行命令ps F還是會報錯。
十、Linux ps命令綜合解析10.1、常用選項摘要本文對linux ps命令的104個短選項都進行了說明,其中只有一部分選項比較常用,下面根據我的經驗推薦給大家重點關注:
選項-e:顯示所有進程的記錄,記住這個參數就可以保證把當前系統的所有進程都輸出。需要篩選進程時,可以結合grep等文本處理命令實現目的。
選項h:選中時可以隱藏輸出結果的標題欄信息,在一些自動化腳本中使用此參數可以去除頁頭信息。
選項k:通過此選項可以實現對輸出結果的排序。
選項-L:通過此選項可以把多線程的進程展開每個線程的細顆粒度。
選項-l:或選項l,此選項可以列出進程的最基本信息,包括s、pid、ppid、time和ucmd等欄位信息。
選項u:此選項可以列出cpu使用率、mem使用率、rss內存等欄位信息。
選項-o:或選項o,通過此選項可以自定義輸出符合自己需求的欄位信息。
Linux ps命令的168個輸出欄位,我們也對大部分進行了介紹。下面根據經驗推薦給大家一些常用的關注。
結語Linux ps命令博大精深,以上內容可能不一定完整。如果大家覺得文章中有任何補充,請加群反饋信息。如果你對ps命令使用還有其他疑問,也歡迎加群答疑。
原文連結:值得收藏,史上最全Linux ps命令詳解,轉自AliDataOps 公眾號,作者聞茂泉。
點擊閱讀原文,訪問大會官網