About me

Wednesday 26 October 2016

[Linux] pidstat - 行程(任務)資源統計

pidstat

pidstat是Linux 裡面一套統計/監控目前被kernel所管理的任務(task)的軟體。使用前必須先掛載proc。主要有底下幾種方式顯示統計數據:

1. 顯示區間和顯示筆數。
2. 根據特定task為單位。
3. 根據IO。
4. 根據PID。
5. CPU使用量。
6. 分頁錯誤(page faults)和記憶體使用量(memory utilization)。
7. 堆疊(stack utilization)。
8. task切換分頁。

(這文章並不是在同一天,同一台主機內寫的,所以顯示數據的hostname, CPU,還有裡面的例子等等資訊可能會不太一樣,並且以下內容都是以版本11.2.0所撰寫)



語法 pidstat [ -d ] [ -h ] [ -I ] [ -l ] [ -R ] [ -r ] [ -s ] [ -t ] [ -U [ username ] ] [ -u ] [ -V ] [ -v ] [ -w ] [ -C comm ] [ -G process_name ] [ -p { pid [,...] | SELF | ALL } ] [ -T { TASK | CHILD | ALL } ] [ interval [ count ] ]
安裝 Ubuntu apt install sysstat Redhat/CentOs yum install sysstat
顯示區間和顯示筆數 習慣在linux上顯示統計數據的人就會知道,通常參數都會搭配兩個數字 -「interval」和「count」,來代表你多久要統計一次和總共要統計幾次,以下面的例子來說: pidstat -U -C pidstat 2 5 情境就是,我想要顯示在系統裡的task - pidstat的統計資料,每2秒統計1次,總共顯示5筆,並且把UID給置換成user name,數據顯示如下: root@hugh-MS:/home/hugh# pidstat -U -C pidstat 2 5 Linux 4.4.0-45-generic (hugh-MS) 10/25/2016 _x86_64_ (1 CPU) 09:09:08 AM USER PID %usr %system %guest %CPU CPU Command 09:09:10 AM USER PID %usr %system %guest %CPU CPU Command 09:09:12 AM root 4097 0.00 0.50 0.00 0.50 0 pidstat 09:09:12 AM USER PID %usr %system %guest %CPU CPU Command 09:09:14 AM USER PID %usr %system %guest %CPU CPU Command 09:09:16 AM root 4097 0.00 0.51 0.00 0.51 0 pidstat 09:09:16 AM USER PID %usr %system %guest %CPU CPU Command 09:09:18 AM root 4097 0.50 0.00 0.00 0.50 0 pidstat Average: USER PID %usr %system %guest %CPU CPU Command Average: root 4097 0.10 0.20 0.00 0.30 - pidstat 上面可以很清楚的看到,只有三筆資料,而且前兩筆是分別花了0.50和0.52的system time,最後一筆花了0.50的user space time,最後還有全部的平均時間。 這邊要特別注意的是,如果沒有特別指定task,像是: pidstat -U 2 5 這樣子的用法,它並不會顯示所有的Task,而是只會顯示在統計期間裡,有活動的所有task才會顯示。 如果不指定「interval」或是指定「0」的話,統計預設就會從系統開機就開始計算。
根據特定task為單位 Task name root@hugh-MS:/home/hugh# pidstat -U -C bash Linux 4.4.0-45-generic (hugh-MS) 10/23/2016 _x86_64_ (8 CPU) 05:10:32 PM USER PID %usr %system %guest %CPU CPU Command 05:10:32 PM hugh 5834 0.00 0.00 0.00 0.00 4 bash 05:10:32 PM hugh 9384 0.00 0.00 0.00 0.00 5 bash 05:10:32 PM root 9402 0.00 0.00 0.00 0.00 1 bash 因為參數有加『-U』,所以顯示的是real user name 而不是預設的UID,在這個例子我想要看的是統計目前所有bash的CPU使用率,所以使用參數『-C』後面加task的名字。 底下簡單介紹一下欄位資訊: 第一行顯示的分別是『kernel版本資訊』,『hostname』,『今天日期』,『OS位元數』,『CPU數』。 第二行開始,第一,二,三欄分別是『統計的時間』,『啟動這個task的user name(如果沒有加-U的話就會變成顯示UID)』,『這個task的process ID』。接下來的欄位如下: %usr: 這個task在user level執行的CPU百分比,這個欄位並沒有紀錄包含跑虛擬處理器的時間。 %system: 這個task在system level執行的CPU百分比。 %guest: 這個task在虛擬機(虛擬處理器)上的CPU百分比。 %CPU: 這個task的全部CPU時間,如果是在SMP的環境上,並且你有使用『-I』參數的話,這個task的CPU使用量將會被除以全部CPU的總數。 CPU: 這個task總共用到幾個CPU。 顯示所有參數 有時候執行一個參數時,後面不同的參數也會造成不同的CPU使用率,所以如果你想要看每個task後面有什麼參數的話,可以加一個「-l」: pidstat -U -C bash -l 複數特定task 如果是要顯示複數的task,就可以用底下的做法: pidstat -C "fox|bird" -r -p ALL Task id 如果想要根據pid來統計資料,可以針對底下這個語法: pidstat -p {<pid>[,....] | SELF | ALL } 基本上 pidstatpidstat -p ALLpidstat -u 是同一件事,都是列出所有的task。 但是如果你要列出一些特定的pid的話,可以參考底下的例子: pidstat -p 5834,9384,9402 就只會列出你想要看的資料: root@hugh-MS:/home/hugh# pidstat -p 5834,9384,9402 Linux 4.4.0-45-generic (hugh-MS) 10/23/2016 _x86_64_ (8 CPU) 08:53:30 PM UID PID %usr %system %guest %CPU CPU Command 08:53:30 PM 1000 5834 0.00 0.00 0.00 0.00 4 bash 08:53:30 PM 1000 9384 0.00 0.00 0.00 0.00 5 bash 08:53:30 PM 0 9402 0.00 0.00 0.00 0.00 0 bash 顯示所有相關執行序(thread)和檔案描述子(file discription)的總數 下面這個例子會列出所有這個task所相關的執行序和檔案描述子(使用參數「-v」): root@hugh-MS:/home/hugh# pidstat -C sshd -v Linux 4.4.0-45-generic (hugh-MS) 10/25/2016 _x86_64_ (1 CPU) 09:41:37 AM UID PID threads fd-nr Command 09:41:37 AM 0 914 1 5 sshd 09:41:37 AM 0 2897 1 8 sshd 09:41:37 AM 1000 2931 1 12 sshd 以上面的例子,可以看到兩個欄位「threads」,「fd-nr」: threads: 和這個task所繫結(associated)的所有執行緒總數。 fd-nr: 和這個task所繫結(associated)的所有檔案描述子總數。 子行程 pidstat [ -T { TASK | CHILD | ALL } ] 這個參數可以顯示更多子行程的資訊,但是只適用於『記憶體』和『CPU模式』,官方文件是稱作這個資料叫做『global statistics』,以下直接舉兩個例子來看: root@hugh-MS:/home/hugh# pidstat -C bash -T TASK Linux 4.4.0-45-generic (hugh-MS) 10/26/2016 _x86_64_ (8 CPU) 10:33:04 PM UID PID %usr %system %guest %CPU CPU Command 10:33:04 PM 1000 6104 0.00 0.00 0.00 0.00 5 bash 10:33:04 PM 0 6724 0.00 0.00 0.00 0.00 5 bash root@hugh-MS:/home/hugh# pidstat -C bash -T CHILD Linux 4.4.0-45-generic (hugh-MS) 10/26/2016 _x86_64_ (8 CPU) 10:33:07 PM UID PID usr-ms system-ms guest-ms Command 10:33:07 PM 1000 6104 410 100 0 bash 10:33:07 PM 0 6724 170 160 0 bash root@hugh-MS:/home/hugh# pidstat -C bash -T ALL Linux 4.4.0-45-generic (hugh-MS) 10/26/2016 _x86_64_ (8 CPU) 10:33:12 PM UID PID %usr %system %guest %CPU CPU Command 10:33:12 PM 1000 6104 0.00 0.00 0.00 0.00 5 bash 10:33:12 PM 0 6724 0.00 0.00 0.00 0.00 5 bash 10:33:12 PM UID PID usr-ms system-ms guest-ms Command 10:33:12 PM 1000 6104 410 100 0 bash 10:33:12 PM 0 6724 170 180 0 bash 上面可以清楚看到一樣是根據task - bash來列出CPU相關統計訊息,使用參數『-T TASK』時,輸出內容就跟沒有加一樣,所以代表預設本來就是有『-T TASK』,但是如果參數變成『-T CHILD』,你就會發現內容不太一樣了,不一樣的欄位解釋如下: usr-ms: 顯示這個Task和他的所有子行程在user level下所花費的時間(millisesonds),這個欄位並沒有包含在 虛擬機(Virtual machine)所處理的時間。 system-ms: 同usr-ms,只是是統計system level底下的時間(millisesonds)。 guest-ms: 同usr-ms,只是是統計Virtual machine底下的時間(millisesonds)。 而『-T ALL』則是同時顯示兩個『-T TASK + CHILD』。 上面的例子是說明『TASK』在CPU上面的顯示數據,下面的例子則是換個參數『-r』來看看記憶體的統計數據: root@hugh-MS:/home/hugh# pidstat -C bash -r -T TASK Linux 4.4.0-45-generic (hugh-MS) 10/26/2016 _x86_64_ (8 CPU) 10:53:23 PM UID PID minflt/s majflt/s VSZ RSS %MEM Command 10:53:23 PM 1000 6104 0.20 0.00 30244 5680 0.03 bash 10:53:23 PM 0 6724 0.17 0.00 28680 4052 0.02 bash root@hugh-MS:/home/hugh# pidstat -C bash -r -T CHILD Linux 4.4.0-45-generic (hugh-MS) 10/26/2016 _x86_64_ (8 CPU) 10:53:26 PM UID PID minflt-nr majflt-nr Command 10:53:26 PM 1000 6104 13867 47 bash 10:53:26 PM 0 6724 14926 1 bash root@hugh-MS:/home/hugh# pidstat -C bash -r -T ALL Linux 4.4.0-45-generic (hugh-MS) 10/26/2016 _x86_64_ (8 CPU) 10:53:29 PM UID PID minflt/s majflt/s VSZ RSS %MEM Command 10:53:29 PM 1000 6104 0.20 0.00 30244 5680 0.03 bash 10:53:29 PM 0 6724 0.18 0.00 28684 4056 0.02 bash 10:53:29 PM UID PID minflt-nr majflt-nr Command 10:53:29 PM 1000 6104 13867 47 bash 10:53:29 PM 0 6724 15176 1 bash 如同CPU一樣,只有在加了『-T CHILD』的資料會顯示出兩筆不一樣的數據: minflt-nr: 這個task和其子行程所造成的minor faults總數。 majflt-nr: 這個task和其子行程所造成的major faults總數。 TID and TGID 如果想要看這個Task的TID和TGID可以用參數『-t』。 root@hugh-MS:/home/hugh# pidstat -C bash -t Linux 4.4.0-45-generic (hugh-MS) 10/26/2016 _x86_64_ (8 CPU) 11:01:56 PM UID TGID TID %usr %system %guest %CPU CPU Command 11:01:56 PM 1000 6104 - 0.00 0.00 0.00 0.00 5 bash 11:01:56 PM 1000 - 6104 0.00 0.00 0.00 0.00 5 |__bash 11:01:56 PM 0 6724 - 0.00 0.00 0.00 0.00 3 bash 11:01:56 PM 0 - 6724 0.00 0.00 0.00 0.00 3 |__bash
Task切換分頁 根據記憶體管理的paging,每個process在執行過程中間,總是會有很多的context switch,這個參數就是主要統計這個部份,這個功能在kernel 2.6.23之後才支援。如下語法: root@hugh-MS:/home/hugh# pidstat -C sshd -w Linux 4.4.0-45-generic (hugh-MS) 10/25/2016 _x86_64_ (1 CPU) 09:15:25 AM UID PID cswch/s nvcswch/s Command 09:15:25 AM 0 914 0.02 0.01 sshd 09:15:25 AM 0 2897 0.03 0.01 sshd 09:15:25 AM 1000 2931 0.86 0.03 sshd 以上重複的欄位就不再追述,有差異的主要是兩個「cswch/s」,「nvcswch/s」 cswch/s: 每秒這個task所做的自主性(voluntary) context switch總數,通常一個自主性的context switch都是因為這個Task需要的資源無法取得,所以自動進入睡眠後等待再次進入排程,或是主動將資源讓給其他的process。 nvcswch/s: 每秒這個task所做的非自主性(non voluntary) context switch 總數,通常是這個task的time slice 已經用完了,所以被強制的context switch 給其他task使用。
根據IO 想要根據IO來顯示report的資料(kernel 2.6.20以後的版本才支援),可以使用底下語法: pidstat -C bash -d 結果如底下所示: root@hugh-MS:/home/hugh# pidstat -C bash -d Linux 4.4.0-45-generic (hugh-MS) 10/25/2016 _x86_64_ (1 CPU) 09:17:41 AM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command 09:17:41 AM 1000 1585 0.84 0.00 0.00 60 bash 09:17:41 AM 0 1624 55.10 32.99 0.88 3 bash 09:17:41 AM 1000 2932 0.10 0.00 0.00 15 bash 09:17:41 AM 0 2962 2.51 0.00 0.00 5 bash 主要為三個欄位「KB_rd/s」,「KB_rd/s」,「KB_ccwr/s」: KB_rd/s: 每秒這個Task從disk所讀取的資料量,單位是kilobytes。 KB_wr/s: 每秒這個Task所寫到disk的資料量,單位是kilobytes。 KB_ccwr/s: 如果有資料要寫到disk裡,但是又被這個Task所取消的話,就會記錄到這邊。通常是這個task去truncate一些dirty的pagecache才會發生。
分頁錯誤(page faults)和記憶體使用量(memory utilization) 如果沒有特別加參數的話,通常這個指令會列出的是CPU使用量,但是如果你要看記憶體使用量就必須要另加參數「-r」,這個參數會顯示出所有分頁錯誤和記憶體使用量。 相關範例如下: root@hugh-MS:/home/hugh# pidstat -r -C bash Linux 4.4.0-45-generic (hugh-MS) 10/23/2016 _x86_64_ (8 CPU) 05:17:52 PM UID PID minflt/s majflt/s VSZ RSS %MEM Command 05:17:52 PM 1000 5834 0.03 0.00 29984 5384 0.03 bash 05:17:52 PM 1000 9384 0.03 0.00 29984 5328 0.03 bash 05:17:52 PM 0 9402 0.04 0.00 28668 4016 0.02 bash minflt/s: 每秒這個task所造成的minor faults的總數,而且這些是在沒有從disk那邊讀取memory page的狀態下所統計的。 majflt/s: 同上,只是是每秒的major faults。 VSZ: Virtual Size的縮寫,代表這整個task的虛擬記憶體使用量(單位為kilobytes)。 RSS: Resident Set Size的縮寫,這個task所使用的實際實體記憶體(單位為kilobytes)。 %MEM: 這個task所使用的實體記憶體量。
堆疊(stack utilization) 每個process之中都會有規劃記憶體來當成stack,這部份博大精深,所以不在這邊介紹, pid的指令有辦法去看到系統分配給這個task的stack size和已經用了多少的size,只要如下面一樣, 加個『-s』 就好。 root@hugh-MS:/home/hugh# pidstat -p 5834,9384,9402 -s Linux 4.4.0-45-generic (hugh-MS) 10/23/2016 _x86_64_ (8 CPU) 09:24:15 PM UID PID StkSize StkRef Command 09:24:15 PM 1000 5834 136 20 bash 09:24:15 PM 1000 9384 136 20 bash 09:24:15 PM 0 9402 136 24 bash 主要是兩個欄位: StkSize: 系統分配給這個process的保留stack,單位是kilobytes,但是不一定會使用到。 StkRef: 這個task已經使用了多少的記憶體來當stack,單位一樣是kilobytes。
Priority and scheduling policy 列出排程的real priority 和其policy,這部份有興趣者,請參考Robert Love 的Linux Kernel Development 的章節 - Process Scheduling。 root@hugh-MS:/home/hugh# pidstat -C watchdog -R Linux 4.4.0-45-generic (hugh-MS) 10/26/2016 _x86_64_ (8 CPU) 10:56:35 PM UID PID prio policy Command 10:56:35 PM 0 10 99 FIFO watchdog/0 10:56:35 PM 0 11 99 FIFO watchdog/1 10:56:35 PM 0 16 99 FIFO watchdog/2 10:56:35 PM 0 21 99 FIFO watchdog/3 10:56:35 PM 0 26 99 FIFO watchdog/4 10:56:35 PM 0 31 99 FIFO watchdog/5 10:56:35 PM 0 36 99 FIFO watchdog/6 10:56:35 PM 0 41 99 FIFO watchdog/7
使用環境變數 pidstat這個指令因為會輸出一些時間數據,所以會用到『S_TIME_FORMAT』這個環境變數,如果這個變數不存在的話,就會直接抓『locale』底下的LC_TIME來用,但是如果有這個變數,而且也符合格式的話,就會忽略locale的資訊,直接採用ISO 8601的格式(YYYY-MM-DD)。
Ref man pidstat

No comments:

Post a Comment