1. 程式人生 > 實用技巧 >14 Linux程序管理

14 Linux程序管理

1.介紹

1.什麼是程序

比如: 開發寫的程式碼我們稱為程式,那麼將開發的程式碼執行起來。我們稱為程序。
總結一句話就是: 當我們執行一個程式,那麼我們將執行的程式叫程序。
PS1: 當程式執行為程序後,系統會為該程序分配記憶體,以及程序執行的身份和許可權。
PS2: 在程序執行的過程中,系統會有各種指標來表示當前執行的狀態。

2.程式和程序的區別

1.程式是資料和指令的集合,是一個靜態的概念。比如/bin/ls、/bin/cp等二進位制檔案。同時程式可以長期存在系統中。
2.程序是程式執行的過程,是一個動態的概念。程序是存在生命週期的概念的,也就是說程序會隨著程式的終止而銷燬,不會永久存在系統中。

3.程序的生命週期

生命週期就是指一個物件的生老病死。用處很廣。

當父程序接收到任務排程時,會通過fock派生子程序來處理,那麼子程序會繼承父程序屬性。
1.子程序在處理任務程式碼時,父程序會進入等待狀態中…
2.子程序在處理任務程式碼後,會執行退出,然後喚醒父程序來回收子程序的資源。
3.如果子程序在處理任務過程中,父程序退出了,子程序沒有退出,那麼這些子程序就沒有父程序來管理了,就變成殭屍程序。
PS: 每個程序都父程序的PPID,子程序則叫PID。

例: 假設現在我是蔣先生(system程序)….故事持續中…..

2.監控程序狀態

程式在執行後,我們需要了解程序的執行狀態。檢視程序的狀態分為: 靜態和動態兩種方式

1.使用ps命令檢視當前的程序狀態(靜態)

1)示例、ps -aux常用組合,檢視程序 使用者、PID、佔用cpu百分比、佔用記憶體百分比、狀態、執行的命令等

狀態 描述
USER 啟動程序的使用者
PID 程序執行的ID號
%CPU 程序佔用CPU百分比
%MEM 程序佔用記憶體百分比
VSZ 程序佔用虛擬記憶體大小 (單位KB)
RSS 程序佔用實體記憶體實際大小 (單位KB)
TTY 程序是由哪個終端執行啟動的tty1、pts/0等 ?表示核心程式與終端無關(遠端連線會通過tty開啟一個bash:tty)
STAT 程序執行過程中的狀態 man ps (/STATE)
START 程序的啟動時間
TIME 程序佔用 CPU 的總時間(為0表示還沒超過秒)
COMMAND 程式的執行指令,[ 方括號 ] 屬於核心態的程序。 沒有 [ ] 的是使用者態程序。systemctl status 指令

2.STAT狀態的S、Ss、S+、R、R、S+等等,都是什麼意思?

STAT基本狀態 描述 STAT狀態+符號 描述
R 程序執行 s 程序是控制程序, Ss程序的領導者,父程序
S 可中斷睡眠 < 程序執行在高優先順序上,S<優先順序較高的程序
T 程序被暫停 N 程序執行在低優先順序上,SN優先順序較低的程序
D 不可中斷睡眠 + 當前程序執行在前臺,R+該表示程序在前臺執行(正在io操作,一旦停止,資料丟失)
Z 殭屍程序 l 程序是多執行緒的,Sl表示程序是以執行緒方式執行

案例一、PS命令檢視程序狀態切換

#1.在終端1上執行vim
[root@lqz ~]# vim oldboy

#2.在終端2上執行ps命令檢視狀態
[root@lqz ~]# ps aux|grep oldboy    #S表示睡眠模式,+表示前臺執行
root      58118  0.4  0.2 151788  5320 pts/1    S+   22:11   0:00 oldboy
root      58120  0.0  0.0 112720   996 pts/0    R+   22:12   0:00 grep --color=auto oldboy
#在終端1上掛起vim命令,按下:ctrl+z 

#3.回到終端2再次執行ps命令檢視狀態
[root@lqz ~]# ps aux|grep oldboy    #T表示停止狀態
root      58118  0.1  0.2 151788  5320 pts/1    T    22:11   0:00 vim oldboy
root      58125  0.0  0.0 112720   996 pts/0    R+   22:12   0:00 grep --color=auto oldboy

案例二、PS命令檢視不可中斷狀態程序

#1.使用tar打包檔案時,可以通過終端不斷檢視狀態,由S+,R+變為D+
[root@lqz ~]# tar -czf etc.tar.gz /etc/ /usr/ /var/

[root@lqz ~]# ps aux|grep tar|grep -v grep
root      58467  5.5  0.2 127924  5456 pts/1    R+   22:22   0:04 tar -czf etc.tar.gz /etc/ 
[root@lqz ~]# ps aux|grep tar|grep -v grep
root      58467  5.5  0.2 127088  4708 pts/1    S+   22:22   0:03 tar -czf etc.tar.gz /etc/ 
[root@lqz ~]# ps aux|grep tar|grep -v grep
root      58467  5.6  0.2 127232  4708 pts/1    D+   22:22   0:03 tar -czf etc.tar.gz /etc/

2.使用top命令檢視當前的程序狀態(動態)

任務 含義
Tasks: 129 total 當然程序的總數
1 running 正在執行的程序數
128 sleeping 睡眠的程序數
0 stopped 停止的程序數
0 zombie 殭屍程序數
%Cpu(s) 平均cpu使用率,按1 檢視每個cup具體狀態
0.7 us 使用者程序佔用cpu百分比
0.7 sys 核心程序佔用百分比
0.0 ni 優先順序程序佔用cpu的百分比
98.7 id 空閒cup
0.0 wa CPU等待IO完成的時間,大量的io等待,會變高
0.0 hi 硬中斷,佔的CPU百分比
0.0 si 軟中斷,佔的CPU百分比
0.0 st 虛擬機器佔用物理CPU的時間
# w     load average:平均負載 一分鐘,5分鐘,15分鐘
 04:05:43 up 11:35,  3 users,  load average: 0.00, 0.01, 0.05
# uptime
 04:06:21 up 11:35,  3 users,  load average: 0.00, 0.01, 0.05

PS: 如何理解中斷這個東西

top 常見指令

字母 含義
h 檢視幫出
1 數字1,顯示所有CPU核心的負載
z 以高亮顯示資料
b 高亮顯示處於R(進行中)狀態的程序
M 按記憶體使用百分比排序輸出
P 按CPU使用百分比排序輸出
q 退出top
# 第三方top
htop,top高階:yum install htop -y
iftop網絡卡流量:yum install iftop -y
glances,直觀的顯示:yum install glances -y
  -rz上傳檔案,可以動態看到,網絡卡情況

3.管理程序狀態

當程式執行為程序後,如果希望停止程序,怎麼辦呢? 那麼此時我們可以使用linux的kill命令對程序傳送關閉訊號。當然除了kill、還有killall,pkill

1.使用kill -l列出當前系統所支援的訊號


雖然linux支援訊號很多,但是我們僅列出我們最為常用的3個訊號

數字編號 訊號含義 訊號翻譯
1 SIGHUP 通常用來重新載入配置檔案,重新讀取一次引數的配置檔案 (類似 reload)
9 SIGKILL 強制殺死程序(有狀態的服務(存磁碟的,如mysql)強制停止可能會導致下次起不來)
15 SIGTERM 終止程序,預設kill使用該訊號

1.我們使用kill命令殺死指定PID的程序。

#1.給 vsftpd 程序傳送訊號 1,15
[root@lqz ~]# yum -y install vsftpd
[root@lqz ~]# systemctl start vsftpd
[root@lqz ~]# ps aux|grep vsftpd

#2.傳送過載訊號,例如 vsftpd 的配置檔案發生改變,希望重新載入
[root@lqz ~]# kill -1 9160

#3.傳送停止訊號,當然vsftpd 服務有停止的指令碼 systemctl stop vsftpd
[root@lqz ~]# kill 9160

#4.傳送強制停止訊號,當無法停止服務時,可強制終止訊號
[root@lqz ~]# kill -9 9160

2.Linux系統中的killall、pkill命令用於殺死指定名字的程序。我們可以使用kill命令殺死指定程序PID的程序,如果要找到我們需要殺死的程序,我們還需要在之前使用ps等命令再配合grep來查詢程序,而killall、pkill把這兩個過程合二為一,是一個很好用的命令。

#例0、通過服務名稱殺掉程序
[root@lqz ~]# vim nginx.conf   # 修改為worker_processes  10;
[root@lqz ~]# kill -1 26093    # 平滑reload nginx,可以看到很多ngixn程序
[root@lqz ~]# kill 26121      # 殺掉一個子程序,會迅速的被master啟動起來,只是id號不一致了

[root@lqz ~]# kill  26093    # 主程序,子程序都會被殺掉 

#例1、通過服務名稱殺掉程序
[root@lqz ~]# pkill nginx
[root@lqz ~]# killall nginx

#例2、使用pkill踢出從遠端登入到本機的使用者,終止pts/0上所有程序, 並且bash也結束(使用者被強制退出)
[root@lqz ~]# pkill -9 bash

# 一般程式都會有自己的啟動和停止
/usr/local/nginx/sbin/nginx -h

4.管理後臺程序

1.什麼是後臺程序

通常程序都會在終端前臺執行,一旦關閉終端,程序也會隨著結束,那麼此時我們就希望程序能在後臺執行,就是將在前臺執行的程序放入後臺執行,這樣及時我們關閉了終端也不影響程序的正常執行。

2.我們為什麼要將程序放入後臺執行

比如:我們此前在國內伺服器往國外伺服器傳輸大檔案時,由於網路的問題需要傳輸很久,如果在傳輸的過程中出現網路抖動或者不小心關閉了終端則會導致傳輸失敗,如果能將傳輸的程序放入後臺,是不是就能解決此類問題了。

3.使用什麼工具將程序放入後臺

早期的時候大家都選擇使用&符號將程序放入後臺,然後在使用jobs、bg、fg等方式檢視程序狀態,但太麻煩了。也不直觀,所以我們推薦使用screen。

1.jobs、bg、fg的使用(強烈不推薦,瞭解即可)

[root@lqz ~]# sleep 3000 & //執行程式(時),讓其在後臺執行 
[root@lqz ~]# sleep 4000 //^Z,將前臺的程式掛起(暫停)到後臺 
[2]+ Stopped sleep 4000
[root@lqz ~]# ps aux |grep sleep
[root@lqz ~]# jobs  //檢視後臺作業
[1]- Running sleep 3000 & 
[2]+ Stopped sleep 4000

[root@lqz ~]# bg %2     //讓作業 2 在後臺執行
[root@lqz ~]# fg %1     //將作業 1 調回到前臺
[root@lqz ~]# kill %1   //kill 1,終止 PID 為 1 的程序

[root@lqz ~]# (while :; do date; sleep 2; done) & //程序在後臺執行,但輸出依然在當前終端
[root@lqz ~]# (while :; do date; sleep 2; done) &>/dev/null &

2.screen的使用(強烈推薦,生產必用)

#1.安裝
[root@oldboy ~]# yum install screen -y

#2.開啟一個screen視窗,指定名稱
[root@oldboy ~]# screen -S wget_mysql

#3.在screen視窗中執行任務即可
[root@oldboy ~]# wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz --no-check-certificate

#4.平滑的退出screen,但不會終止screen中的任務。注意: 如果使用exit 才算真的關閉screen視窗
ctrl+a+d

#5.檢視當前正在執行的screen有哪些
[root@oldboy ~]# screen -list
There is a screen on:
    22058.wget_mysql    (Detached)
1 Socket in /var/run/screen/S-root.

#6.進入正在執行的screen
[root@oldboy ~]# screen -r wget_mysql
[root@oldboy ~]# screen -r 22058

#7 終止(ctrl+d),退出才能停止screen
exit

5.程序的優先順序[進階]

1.什麼優先順序

優先順序指的是優先享受資源,比如排隊買票時,軍人優先、老人優先。等等

2.為什麼要有系統優先順序

舉個例子: 海底撈火鍋正常情況下響應就特別快,那麼當節假日來臨時人員突增則會導致處理請求特別慢,那麼假設我是海底撈VIP客戶(最高優先順序),無論門店多麼繁忙,我都不用排隊,海底撈人員會直接服務於我,滿足我的需求。至於沒有VIP的人員(較低優先順序)則進入排隊等待狀態。(PS: 至於等多久,那…..)

3.系統中如何給程序配置優先順序?

在啟動程序時,為不同的程序使用不同的排程策略。
nice 值越高: 表示優先順序越低,例如+19,該程序容易將CPU 使用量讓給其他程序。
nice 值越低: 表示優先順序越高,例如-20,該程序更不傾向於讓出CPU。

  1. 使用top或ps命令檢視程序的優先順序
#1.使用top可以檢視nice優先順序。  
NI: 實際nice級別,預設是0。 
PR: 顯示nice值,-20對映到0,+19對映到39

PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
1083 root      20   0  298628   2808   1544 S  0.3  0.1   2:49.28 vmtoolsd
5    root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:+

#2.使用ps檢視程序優先順序
[root@m01 ~]# ps axo command,nice |grep sshd|grep -v grep
/usr/sbin/sshd -D             0
sshd: root@pts/2              0

  1. nice指定程式的優先順序。語法格式 nice -n 優先順序數字 程序名稱
#1.開啟vim並且指定程式優先順序為-5
[root@m01 ~]# nice -n -5 vim &
[1] 98417

#2.檢視該程序的優先順序情況
[root@m01 ~]# ps axo pid,command,nice |grep 98417
 98417 vim                         -5

  1. renice命令修改一個正在執行的程序優先順序。語法格式 renice -n 優先順序數字 程序pid
#1.檢視sshd程序當前的優先順序狀態
[root@m01 ~]# ps axo pid,command,nice |grep 摺疊shd
 70840 sshd: root@pts/2              0
 98002 /usr/sbin/sshd -D             0
 
#2.調整sshd主程序的優先順序
[root@m01 ~]# renice -n -20 98002
98002 (process ID) old priority 0, new priority -20

#3.調整之後記得退出終端
[root@m01 ~]# ps axo pid,command,nice |grep 摺疊shd
 70840 sshd: root@pts/2              0
 98002 /usr/sbin/sshd -D           -20
[root@m01 ~]# exit

#4.當再次登陸sshd服務,會由主程序fork子程序(那麼子程序會繼承主程序的優先順序)
[root@m01 ~]# ps axo pid,command,nice |grep 摺疊shd
 98002 /usr/sbin/sshd -D           -20
 98122 sshd: root@pts/0            -20

生產案例、Linux出現假死,怎麼辦,又如何通過nice解決?

6.系統平均負載[進階]

每次發現系統變慢時,我們通常做的第一件事,就是執行 top 或者 uptime 命令,來了解系統的負載情況。比如像下面這樣,我在命令列裡輸入了 uptime 命令,系統也隨即給出了結果。

[root@m01 ~]# uptime
 04:49:26 up 2 days,  2:33,  2 users,  load average: 0.70, 0.04, 0.05
#我們已經比較熟悉前面幾列,它們分別是當前時間、系統執行時間以及正在登入使用者數。

# 而最後三個數字呢,依次則是過去 1 分鐘、5 分鐘、15 分鐘的平均負載(Load Average)。

1.什麼是平均負載

平均負載不就是單位時間內的 CPU 使用率嗎?上面的 0.70,就代表 CPU 使用率是 70%。其實上並…..
那到底如何理解平均負載: 平均負載是指單位時間內,系統處於可執行狀態和不可中斷狀態的平均程序數,也就是平均活躍程序數, PS: 平均負載與 CPU 使用率並沒有直接關係。

2.可執行狀態和不可中斷狀態是什麼

1.可執行狀態程序,是指正在使用 CPU 或者正在等待 CPU 的程序,也就是我們ps 命令看到處於 R 狀態的程序。
2.不可中斷程序,(你做什麼事情的時候是不能打斷的?) 系統中最常見的是等待硬體裝置的 I/O 響應,也就是我們 ps 命令中看到的 D 狀態(也稱為 Disk Sleep)的程序。
例如: 當一個程序向磁碟讀寫資料時,為了保證資料的一致性,在得到磁盤迴復前,它是不能被其他程序或者中斷打斷的,這個時候的程序就處於不可中斷狀態。如果此時的程序被打斷了,就容易出現磁碟資料與程序資料不一致的問題。所以,不可中斷狀態實際上是系統對程序和硬體裝置的一種保護機制。

劃重點,因此你可以簡單理解為,平均負載其實就是單位時間內的活躍程序數。

3.那平均負載為多少時合理

最理想的狀態是每個 CPU 上都剛好執行著一個程序,這樣每個 CPU 都得到了充分利用。所以在評判平均負載時,首先你要知道系統有幾個 CPU,這可以通過 top 命令獲取,或grep 'model name' /proc/cpuinfo

例1、假設現在在 4、2、1核的CPU上,如果平均負載為 2 時,意味著什麼呢?
Q1.在4 個 CPU 的系統上,意味著 CPU 有 50% 的空閒。
Q2.在2 個 CPU 的系統上,意味著所有的 CPU 都剛好被完全佔用。
Q3.而1 個 CPU 的系統上,則意味著有一半的程序競爭不到 CPU。

PS: 平均負載有三個數值,我們應該關注哪個呢?
實際上,我們都需要關注。就好比上海4月的天氣,如果只看晚上天氣,感覺在過冬天呢。但如果你結合了早上、中午、晚上三個時間點的溫度來看,基本就可以全方位瞭解這一天的天氣情況了。

1.如果 1 分鐘、5 分鐘、15 分鐘的三個值基本相同,或者相差不大,那就說明系統負載很平穩。
2.但如果 1 分鐘的值遠小於 15 分鐘的值,就說明系統最近 1 分鐘的負載在減少,而過去 15 分鐘內卻有很大的負載。
3.反過來,如果 1 分鐘的值遠大於 15 分鐘的值,就說明最近 1 分鐘的負載在增加,這種增加有可能只是臨時性的,也有可能還會持續上升,所以就需要持續觀察。
PS: 一旦 1 分鐘的平均負載接近或超過了 CPU 的個數,就意味著系統正在發生過載的問題,這時就得分析問題,並要想辦法優化了

在來看個例子3、假設我們在有2個 CPU 系統上看到平均負載為 2.73,6.90,12.98
那麼說明在過去1 分鐘內,系統有 136% 的超載 (2.73/2=136%)
而在過去 5 分鐘內,有 345% 的超載 (6.90/2=345%)
而在過去15 分鐘內,有 649% 的超載,(12.98/2=649%)
但從整體趨勢來看,系統的負載是在逐步的降低。

4.那麼在實際生產環境中,平均負載多高時,需要我們重點關注呢?

當平均負載高於 CPU 數量 70% 的時候,你就應該分析排查負載高的問題了。一旦負載過高,就可能導致程序響應變慢,進而影響服務的正常功能。
但 70% 這個數字並不是絕對的,最推薦的方法,還是把系統的平均負載監控起來,然後根據更多的歷史資料,判斷負載的變化趨勢。當發現負載有明顯升高趨勢時,比如說負載翻倍了,你再去做分析和調查。

5.平均負載與 CPU 使用率有什麼關係

在實際工作中,我們經常容易把平均負載和 CPU 使用率混淆,所以在這裡,我也做一個區分。可能你會疑惑,既然平均負載代表的是活躍程序數,那平均負載高了,不就意味著 CPU 使用率高嗎?
我們還是要回到平均負載的含義上來,平均負載是指單位時間內,處於可執行狀態和不可中斷狀態的程序數。所以,它不僅包括了正在使用 CPU 的程序,還包括等待 CPU 和等待 I/O 的程序。

而 CPU 使用率,是單位時間內 CPU 繁忙情況的統計,跟平均負載並不一定完全對應。比如:
CPU 密集型程序,使用大量 CPU 會導致平均負載升高,此時這兩者是一致的;
I/O 密集型程序,等待 I/O 也會導致平均負載升高,但 CPU 使用率不一定很高;
大量等待 CPU 的程序排程也會導致平均負載升高,此時的 CPU 使用率也會比較高。

6.平均負載案例分析實戰

下面,我們以三個示例分別來看這三種情況,並用 stress、mpstat、pidstat 等工具,找出平均負載升高的根源。
stress 是 Linux 系統壓力測試工具,這裡我們用作異常程序模擬平均負載升高的場景。
mpstat 是多核 CPU 效能分析工具,用來實時檢視每個 CPU 的效能指標,以及所有 CPU 的平均指標。
pidstat 是一個常用的程序效能分析工具,用來實時檢視程序的 CPU、記憶體、I/O 以及上下文切換等效能指標。

#如果出現無法使用mpstat、pidstat命令檢視%wait指標建議更新下軟體包
wget http://pagesperso-orange.fr/sebastien.godard/sysstat-11.7.3-1.x86_64.rpm
rpm -Uvh sysstat-11.7.3-1.x86_64.rpm

場景一:CPU 密集型程序

1.首先,我們在第一個終端執行 stress 命令,模擬一個 CPU 使用率 100% 的場景:

[root@m01 ~]# stress --cpu 1 --timeout 600

2.接著,在第二個終端執行 uptime 檢視平均負載的變化情況

# 使用watch -d 引數表示高亮顯示變化的區域(注意負載會持續升高)
[root@m01 ~]# watch -d uptime
17:27:44 up 2 days,  3:11,  3 users,  load average: 1.10, 0.30, 0.17

3.最後,在第三個終端執行 mpstat 檢視 CPU 使用率的變化情況

# -P ALL 表示監控所有 CPU,後面數字 5 表示間隔 5 秒後輸出一組資料
[root@m01 ~]# mpstat -P ALL 5
Linux 3.10.0-957.1.3.el7.x86_64 (m01)   2019年04月29日     _x86_64_    (1 CPU)

17時32分03秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
17時32分08秒  all   99.80    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00    0.00
17時32分08秒    0   99.80    0.00    0.20    0.00    0.00    0.00    0.00    0.00    0.00    0.00

#單核CPU所以只有一個all和0

4.從終端二中可以看到,1 分鐘的平均負載會慢慢增加到 1.00,而從終端三中還可以看到,正好有一個 CPU 的使用率為 100%,但它的 iowait 只有 0。這說明,平均負載的升高正是由於 CPU 使用率為 100% 。那麼,到底是哪個程序導致了 CPU 使用率為 100% 呢?可以使用 pidstat 來查詢

# 間隔 5 秒後輸出一組資料
[root@m01 ~]# pidstat -u 5 1
Linux 3.10.0-957.1.3.el7.x86_64 (m01)   2019年04月29日     _x86_64_(1 CPU)

17時33分21秒   UID       PID    %usr %system  %guest    %CPU   CPU  Command
17時33分26秒     0    110019   98.80    0.00    0.00   98.80     0  stress

#從這裡可以明顯看到,stress 程序的 CPU 使用率為 100%。

場景二:I/O 密集型程序

1.首先還是執行 stress 命令,但這次模擬 I/O 壓力,即不停地執行 sync

[root@m01 ~]# stress  --io 1 --timeout 600s

2.然後在第二個終端執行 uptime 檢視平均負載的變化情況:

[root@m01 ~]# watch -d uptime
18:43:51 up 2 days,  4:27,  3 users,  load average: 1.12, 0.65, 0.00

3.最後第三個終端執行 mpstat 檢視 CPU 使用率的變化情況:

# 顯示所有 CPU 的指標,並在間隔 5 秒輸出一組資料
[root@m01 ~]# mpstat -P ALL 5
Linux 3.10.0-693.2.2.el7.x86_64 (bgx.com)   2019年05月07日     _x86_64_    (1 CPU)

14時20分07秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
14時20分12秒  all    0.20    0.00   82.45   17.35    0.00    0.00    0.00    0.00    0.00    0.00
14時20分12秒    0    0.20    0.00   82.45   17.35    0.00    0.00    0.00    0.00    0.00    0.00

#會發現cpu的與核心打交道的sys佔用非常高

4.那麼到底是哪個程序,導致 iowait 這麼高呢?我們還是用 pidstat 來查詢

# 間隔 5 秒後輸出一組資料,-u 表示 CPU 指標
[root@m01 ~]# pidstat -u 5 1
Linux 3.10.0-957.1.3.el7.x86_64 (m01)   2019年04月29日     _x86_64_(1 CPU)
18時29分37秒   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
18時29分42秒     0    127259   32.60    0.20    0.00   67.20   32.80     0  stress
18時29分42秒     0    127261    4.60   28.20    0.00   67.20   32.80     0  stress
18時29分42秒     0    127262    4.20   28.60    0.00   67.20   32.80     0  stress

#可以發現,還是 stress 程序導致的。

場景三:大量程序的場景
當系統中執行程序超出 CPU 執行能力時,就會出現等待 CPU 的程序。

1.首先,我們還是使用 stress,但這次模擬的是 4 個程序

[root@m01 ~]# stress -c 4 --timeout 600

2.由於系統只有 1 個 CPU,明顯比 4 個程序要少得多,因而,系統的 CPU 處於嚴重過載狀態

[root@m01 ~]# watch -d uptime
19:11:07 up 2 days,  4:45,  3 users,  load average: 4.65, 2.65, 4.65

3.然後,再執行 pidstat 來看一下程序的情況:

# 間隔 5 秒後輸出一組資料
[root@m01 ~]# pidstat -u 5 1
平均時間:   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
平均時間:     0    130290   24.55    0.00    0.00   75.25   24.55     -  stress
平均時間:     0    130291   24.95    0.00    0.00   75.25   24.95     -  stress
平均時間:     0    130292   24.95    0.00    0.00   75.25   24.95     -  stress
平均時間:     0    130293   24.75    0.00    0.00   74.65   24.75     -  stress

可以看出,4 個程序在爭搶 1 個 CPU,每個程序等待 CPU 的時間(也就是程式碼塊中的 %wait 列)高達 75%。這些超出 CPU 計算能力的程序,最終導致 CPU 過載。

分析完這三個案例,我再來歸納一下平均負載與CPU
平均負載提供了一個快速檢視系統整體效能的手段,反映了整體的負載情況。但只看平均負載本身,我們並不能直接發現,到底是哪裡出現了瓶頸。所以,在理解平均負載時,也要注意:
平均負載高有可能是 CPU 密集型程序導致的;
平均負載高並不一定代表 CPU 使用率高,還有可能是 I/O 更繁忙了;
當發現負載高的時候,你可以使用 mpstat、pidstat 等工具,輔助分析負載的來源

stress工具使用參考