cpu到達100% 但是找不到使用cpu的進程
一般分析cpu使用率:通過使用 top、vmstat、pidstat 等工具,排查高 CPU 使用率的進程,然后再使用 perf top 工具,定位應用內部函數的問題。
但是!不是所有cpu過高都是這樣分析的,這只是一般情況下可以這樣分析。什么是一般情況?簡單說,通常可以根據工具,就可以找到cpu占有過高的進程!
通過top命令我們知道,系統cpu使用率基本包括
- 進程用戶狀態的運行
- 內核狀態的運行
- 中斷處理的線程
- 等待I/O的線程
- 內核線程
以前看到cpu過高時,簡單的以為是某一個進程占用過大導致的,其實不一定,系統CPU過高,不一定是進程引起的,還有可能是IO過高或者阻塞引起的,也有可能是中斷進程引起的,多方面原因分析:如圖:

如下一個案例
使用TOP命令
$ top
top - 04:58:24 up 14 days, 15:47, 1 user, load average: 3.39, 3.82, 2.74
Tasks: 149 total, 6 running, 93 sleeping, 0 stopped, 0 zombie
%Cpu(s): 77.7 us, 19.3 sy, 0.0 ni, 2.0 id, 0.0 wa, 0.0 hi, 1.0 si, 0.0 st
KiB Mem : 8169348 total, 2543916 free, 457976 used, 5167456 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 7363908 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6947 systemd+ 20 0 33104 3764 2340 S 4.0 0.0 0:32.69 nginx
6882 root 20 0 12108 8360 3884 S 2.0 0.1 0:31.40 docker-containe
15465 daemon 20 0 336696 15256 7576 S 2.0 0.2 0:00.62 php-fpm
15466 daemon 20 0 336696 15196 7516 S 2.0 0.2 0:00.62 php-fpm
15489 daemon 20 0 336696 16200 8520 S 2.0 0.2 0:00.62 php-fpm
6948 systemd+ 20 0 33104 3764 2340 S 1.0 0.0 0:00.95 nginx
15006 root 20 0 1168608 65632 37536 S 1.0 0.8 9:51.09 dockerd
15476 daemon 20 0 336696 16200 8520 S 1.0 0.2 0:00.61 php-fpm
15477 daemon 20 0 336696 16200 8520 S 1.0 0.2 0:00.61 php-fpm
24340 daemon 20 0 8184 1616 536 R 1.0 0.0 0:00.01 stress
24342 daemon 20 0 8196 1580 492 R 1.0 0.0 0:00.01 stress
24344 daemon 20 0 8188 1056 492 R 1.0 0.0 0:00.01 stress
24347 daemon 20 0 8184 1356 540 R 1.0 0.0 0:00.01 stress
...
這次從頭開始看 top 的每行輸出,Tasks 這一行看起來有點奇怪,就緒隊列中居然有 6 個 Running 狀態的進程(6 running),是不是有點多呢?
然后用 pidstat 命令看一下它的 CPU 使用情況:
$ pidstat -p 24344
16:14:55 UID PID %usr %system %guest %wait %CPU CPU Command
奇怪,居然沒有任何輸出。難道是 pidstat 命令出問題了嗎?我們在終端里運行下面的命令,看看 24344 進程的狀態:
# 從所有進程中查找 PID 是 24344 的進程
$ ps aux | grep 24344
root 9628 0.0 0.0 14856 1096 pts/0 S+ 16:15 0:00 grep --color=auto 24344
還是沒有輸出。現在終於發現問題,原來這個進程已經不存在了,所以 pidstat 就沒有任何輸出。既然進程都沒了,那性能問題應該也跟着沒了吧
然后再一次top一下
$ top
...
%Cpu(s): 80.9 us, 14.9 sy, 0.0 ni, 2.8 id, 0.0 wa, 0.0 hi, 1.3 si, 0.0 st
...
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6882 root 20 0 12108 8360 3884 S 2.7 0.1 0:45.63 docker-containe
6947 systemd+ 20 0 33104 3764 2340 R 2.7 0.0 0:47.79 nginx
3865 daemon 20 0 336696 15056 7376 S 2.0 0.2 0:00.15 php-fpm
6779 daemon 20 0 8184 1112 556 R 0.3 0.0 0:00.01 stress
...
好像又錯了。結果還跟原來一樣,用戶 CPU 使用率還是高達 80.9%,系統 CPU 接近 15%,而空閑 CPU 只有 2.8%,Running 狀態的進程有 Nginx、stress 等。
可是,剛剛我們看到 stress 進程不存在了,怎么現在還在運行呢?再細看一下 top 的輸出,原來,這次 stress 進程的 PID 跟前面不一樣了,原來的 PID 24344 不見了,現在的是 6779。
那么問題來了,stress這個進程再不斷的變換PID,是什么原因呢?
一個進程不斷的變換Pid號,無非兩種原因
第一個原因:進程在不停地崩潰重啟,比如因為段錯誤、配置錯誤等等,這時,進程在退出后可能又被監控系統自動重啟了
第二個原因:這些進程都是短時進程,也就是在其他應用內部通過 exec 調用的外面命令。這些命令一般都只運行很短的時間就會結束,很難用 top 這種間隔時間比較長的工具發現
通過這兩種原因,看來,top命令也不是萬能的,也會有些速度快的進程逃過他的檢查(天下武功,唯快不破)
回到問題:stress這個進程不斷的變換PID,又占用用cpu資源,導致cpu過高,這個時候,找到它的父進程,來進行下一步分析
使用pstree命令來看進程關系,找到它的父進程!
看看是不是父進程里有什么調用問題,看看父進程的源碼
一大部分可能是————————————————
由於權限錯誤,大量的 stress 進程在啟動時初始化失敗,進而導致用戶 CPU 使用率的升高。或者是二進制文件里有對stress有大量的調用循環。
問題總結:
碰到常規問題無法解釋的 CPU 使用率情況時,首先要想到有可能是短時應用導致的問題,比如有可能是下面這兩種情況
- 應用里直接調用了其他二進制程序,這些程序通常會運行時間很短,速度非常快,通過top等其他工具不一定能查詢的到
- 應用本身就在不停的崩潰重啟,而啟動過程的資源初始化,很可能會占用大量的CPU,而且這類進程,PID會不斷變更,通常只能通過pstree或者execsnoop找到它的父進程,從父進程所在的應用里查找,找到問題所在,排查問題。
