上海阿里云代理商:阿里云ECS CPU滿載診斷修復全指南
收到ECS CPU使用率驟升至100%的告警,登錄服務(wù)器卻發(fā)現(xiàn)連敲一條命令都卡頓數(shù)秒——這種場景在生產(chǎn)環(huán)境中幾乎不可避免。排查的關(guān)鍵不在于“有沒有高消耗的進程”,而在于能否在系統(tǒng)瀕臨僵死時快速采集到一組時間戳對齊、維度完整的現(xiàn)場數(shù)據(jù)。一份設(shè)計得當?shù)?strong>阿里云ECS CPU滿載排查腳本,能做到比人工敲命令更早觸及根因,且避免遺漏那些一閃而過的短命進程。
一、如何快速定位CPU滿載原因
1. 核心監(jiān)控命令詳解
瓶頸分析不能只盯一個top。mpstat -P ALL能分別展示每顆邏輯核的占用,可以立刻判斷是全核打滿還是單核熱鎖。配合pidstat按進程采樣,比top更適合抓取瞬間飆升的短時任務(wù)。多數(shù)人忽略的一點:CPU使用率拆項中的%wa若持續(xù)超過30%,問題根源常不在計算,而在磁盤I/O,此時進一步查iostat -x比死磕進程列表有效得多。
2. 進程資源占用分析
排查腳本抓取進程樣本時,必須規(guī)避視覺欺騙。挖礦程序常偽裝成[kworker]或[kthread]這類系統(tǒng)線程名,僅靠名稱判斷極容易漏過。更可靠的做法是交叉比對進程的可執(zhí)行文件路徑、父進程關(guān)系和啟動時間——異常進程往往由crontab或隱蔽守護進程拉起,啟動時間與告警起始高度吻合。腳本在采集/proc/[pid]/exe和/proc/[pid]/status時若能標記出這類特征,排查效率會有數(shù)量級的提升。
3. 系統(tǒng)日志排查要點
CPU滿載的誘因不止于進程自身,內(nèi)核層面的OOM Killer活動、硬件錯誤(MCE)同樣會讓系統(tǒng)陷入資源爭搶。/var/log/messages或/var/log/syslog里記錄的Out of memory、mce: [Hardware Error]條目,往往是進程異常飆升的前奏。腳本應(yīng)在前三秒內(nèi)從日志尾部截取最近500行關(guān)鍵字匹配結(jié)果,并與CPU飆升時間線對齊——這一步驟換作人工幾乎不可能在系統(tǒng)卡死的窗口期內(nèi)完成。
二、常見CPU滿載場景與根因
CPU滿載并非單一面孔的問題。在云上運維場景中,我們觀察到至少三類截然不同的觸發(fā)路徑,它們指向的根因與修復策略完全不同。將三者混為一談就急于重啟或擴容,是被動運維的典型特征。
1. 應(yīng)用代碼死循環(huán)
這是最直觀但也最容易被誤判的場景。典型表現(xiàn)為單核或全部核心的 %us(用戶態(tài)CPU)持續(xù)接近100%,而 %wa(I/O等待)與 %sy(內(nèi)核態(tài))占比極低。負載值則取決于死循環(huán)發(fā)生在幾核——如果是單線程死鎖,8核實例的load average可能僅顯示1.0左右,這就容易制造“負載正常但系統(tǒng)卡死”的矛盾現(xiàn)場。
死循環(huán)的根因排查有一個經(jīng)典的“三無”困境:自研應(yīng)用無日志、無異常堆棧輸出、開發(fā)人員無法第一時間到場。此時 perf top 的價值就凸顯出來——它能繞開應(yīng)用層的日志空白,實時抓取CPU熱點函數(shù)的符號名稱。某次生產(chǎn)事故中,我們正是通過 perf top -g 抓到某Java應(yīng)用的 HashMap.get() 函數(shù)占用率異常飆升,才定位到是特定格式的入?yún)⒂|發(fā)了JDK 8早期版本在鏈表轉(zhuǎn)紅黑樹時的退化bug。沒有perf,那次排查至少要多耗掉兩個小時的推測與灰度驗證。
另一個容易被忽略的點是:死循環(huán)不一定出在業(yè)務(wù)代碼本身。不合理的正則表達式回溯、JSON解析庫對畸形數(shù)據(jù)的災(zāi)難性回溯、ORM框架在特定關(guān)聯(lián)查詢下的笛卡爾積展開,都曾在生產(chǎn)環(huán)境制造過CPU滿載事故,而這些代碼路徑通常不會打印業(yè)務(wù)日志。
2. 內(nèi)存泄漏與交換
CPU滿載的第二條路徑繞了個彎——問題本不在CPU,而在內(nèi)存。當應(yīng)用發(fā)生漸進式內(nèi)存泄漏,可用內(nèi)存被蠶食殆盡后,內(nèi)核被迫將很少使用的內(nèi)存頁交換到磁盤上的swap分區(qū)。接下來的連鎖反應(yīng)是:每次被交換出去的內(nèi)存頁需要重新訪問時,都會觸發(fā)一次磁盤I/O讀回操作,而磁盤的吞吐量比內(nèi)存低幾個數(shù)量級,CPU的大量時間耗費在等待I/O完成上,表現(xiàn)為 %wa 持續(xù)偏高。
此時 top 命令看到的CPU使用率可能并不夸張,但系統(tǒng)實際已經(jīng)近乎癱瘓。更隱蔽的是,如果swap交換出去的剛好是某個守護進程的核心內(nèi)存頁,該進程被調(diào)度時會反復觸發(fā)頁面換入,造成CPU使用率的周期性脈沖式?jīng)_高——這種波形在監(jiān)控圖上很容易被誤判為定時任務(wù)觸發(fā)。
在阿里云ECS上,這種場景有一個天然的“報警器”:當系統(tǒng)日志中出現(xiàn) Out of memory: Kill process 的記錄時,其實已經(jīng)晚了,說明內(nèi)核的OOM Killer已經(jīng)介入。更早的信號藏在 /proc/meminfo 的 Committed_AS 字段與 swappiness 參數(shù)的偏離程度中。一個經(jīng)驗值:如果 Committed_AS 超過物理內(nèi)存的1.5倍且swap使用率同時在增長,CPU滿載只是時間問題。
3. 異常系統(tǒng)服務(wù)
第三類場景帶有更強的隱蔽性與破壞性——非法入侵或惡意程序。挖礦木馬是其中最常見的一類,它們通常具備三個特征:進程名偽裝成 [kworker]、/sbin/init 等系統(tǒng)常見名但運行路徑異常;連接已知礦池的TCP端口;以及使用 cgroup 或 taskset 綁定所有CPU核心。
這類進程的排查難點在于“抓不住”。普通運維人員登錄服務(wù)器后習慣執(zhí)行 top 或 htop 觀察,但部分挖礦程序會做反偵察——它們通過劫持 ld.so.preload 動態(tài)鏈接庫,替換系統(tǒng)的 readdir、fopen 等函數(shù),使得 ps、top、lsof 等命令對自身完全透明。此時腳本內(nèi)直接讀取 /proc/[pid]/ 下的原始文件是繞開被篡改的libc庫的唯一可靠手段。
更令人頭疼的是“死后復生”機制。挖礦程序往往配置了多重?;睿篶rontab定時拉起、systemd service單元、甚至篡改 ~/.ssh/authorized_keys 預(yù)留后門。簡單 kill -9 既清理不干凈,也無法阻斷重感染路徑。腳本排查的價值在于一次性輸出“進程快照 + 網(wǎng)絡(luò)連接 + 啟動項 + 計劃任務(wù)”的四維關(guān)聯(lián)視圖,讓隱藏的鏈條暴露出來,而不是逐條命令手工排查。
三、手動排查步驟與工具
在自動化腳本尚未覆蓋、或需要人工驗證的緊急場景下,掌握幾件核心工具的使用邊界,往往比擁有一堆未經(jīng)驗證的“一鍵修復”腳本更可靠。下面拆解三個高頻且常被誤用的手動排查方向。
1. top/htop 診斷使用
許多人打開 top 后會下意識按 P 讓進程按 CPU 使用率排序,然后盯著排第一的進程準備 kill。這種習慣省略掉了最關(guān)鍵的一步:區(qū)分 CPU 時間到底消耗在用戶態(tài)、內(nèi)核態(tài)還是等待 I/O 上。top 默認顯示行里的 %Cpu(s) 會給出 us(用戶態(tài))、sy(內(nèi)核態(tài))、wa(等待 I/O)、st(虛擬機被宿主機偷走的時間)等拆項,這些數(shù)字比排序輸出更能指明方向。一次典型誤判:某次業(yè)務(wù)接口響應(yīng)變慢,運維看到 cc1plus 進程占用 95% CPU 便以為是編譯任務(wù)失控,實際 %wa 已經(jīng)飆到 40%,根因是 NAS 掛載點超時導致大量 D 狀態(tài)進程堆積,CPU 負載純粹由不可中斷睡眠疊加 I/O 等待引起,殺死編譯進程對恢復服務(wù)毫無幫助,反而讓現(xiàn)場更快冷卻。
在阿里云 ECS 環(huán)境里,還應(yīng)留意 %st 字段。虛擬化平臺的 CPU 超賣或宿主機爭搶會導致“CPU 竊取”,此時實例內(nèi) top 顯示 CPU 滿載,但業(yè)務(wù)線程實際獲得的物理計算資源可能不足標稱值的一半。如果 %st 持續(xù)超過 5%,排查方向應(yīng)該從應(yīng)用邏輯轉(zhuǎn)向規(guī)格升配或遷移宿主機,而不是繼續(xù)優(yōu)化代碼。
top 本身也會因系統(tǒng)卡頓而無法啟動,所以手工排查的第一條命令應(yīng)該是 sysctl -w kernel.sysrq=1 預(yù)留后手,然后對排查用的 shell 執(zhí)行 renice -n -5 -p $$ 提升優(yōu)先級,避免連診斷工具都被餓死。監(jiān)控采集必須一次成組:把時間戳、load average、top 前 20 進程列表、/proc/meminfo 的 Swap 行和進程總數(shù)寫入一個帶時間標記的文本文件,而不是分段敲命令,才能保證不同指標在同一個時間斷面上,事后對比時不至于被錯位的數(shù)據(jù)誤導。
2. strace 跟蹤進程
當一個進程 CPU 占用很高但既無日志輸出、又不響應(yīng)請求時,strace 能給出它在干什么的系統(tǒng)級答案。常見做法是對目標 PID 執(zhí)行 strace -f -p,觀察幾秒后 Ctrl+C 停止,然后檢查輸出中高頻重復的系統(tǒng)調(diào)用模式。比如某次排查一個 Java 進程突然吃滿 CPU,開發(fā)團隊堅稱沒有修改代碼,但 strace 日志里每秒出現(xiàn)上千次 futex(FUTEX_WAIT_PRIVATE, ...) = -1 EAGAIN,結(jié)合 perf top 看到 pthread_mutex_lock 占比異常,最終定位到連接池回收線程在某種邊緣條件下陷入熱循環(huán)爭搶鎖。
strace 對短時進程的捕獲同樣有效,但需要換成基于觸發(fā)器的思路:for i in $(seq 1 100); do strace -p 這種快速抽樣循環(huán)或借助 auditd 記錄進程啟動時的系統(tǒng)調(diào)用序列,比肉眼刷 top 更容易抓到那些執(zhí)行時間不足一秒的異常腳本,這類腳本常被挖礦程序用來偽裝為系統(tǒng)服務(wù)。
注意 strace 本身會讓被跟蹤進程性能嚴重下降,在生產(chǎn)環(huán)境使用務(wù)必加 -e trace=file,network 預(yù)篩選,或者先嘗試 perf top -p 獲取函數(shù)級熱點,敲定可疑范圍后再用 strace 深入確認系統(tǒng)調(diào)用參數(shù)細節(jié),避免因附加跟蹤拖垮整個服務(wù)。
3. 定時任務(wù)檢查
進程被殺后再次自動復活,根因多數(shù)不在進程本身,而在于拉起的機制。常規(guī)排查 crontab 之外,更要覆蓋 systemd timer、/etc/cron.hourly、/etc/cron.d 以及用戶級的 ~/.config/autostart 等隱蔽位置。實際案例中,一個看似無害的 */5 * * * * /usr/libexec/kswapd 隱藏在系統(tǒng) crontab 注釋行里,用偽裝的“kswapd”名字讓管理員誤以為是內(nèi)核線程,實際指向一個隨機字符串命名的腳本,該腳本每 5 分鐘從礦池域名拉取最新 payload。對 crontab -l 的輸出應(yīng)全文檢索 curl、wget、base64 -d、/dev/tcp 等關(guān)鍵字,而不是憑肉眼掃過去。
對于用 nohup /tmp/.X11-unix/x 這類方式常駐的守護進程,可以結(jié)合 systemctl list-timers --all 和 ls -l /proc/*/exe | grep deleted 來暴露已經(jīng)被刪除但仍在運行的可執(zhí)行文件。如果懷疑問題周期性復發(fā),在 /etc/crontab 或用戶 crontab 文件頭添加一行 MAILTO="" 以去重郵件噪音,再在腳本觸發(fā)點添加 (date; ps auxf) >> /var/log/cron_trace.log,將拉起的完整進程樹與原任務(wù)時間點綁定,下一次異常復現(xiàn)時可以直接從日志回溯,而不必重新復現(xiàn)現(xiàn)場。
手動排查不是為了代替腳本,而是為編寫真正有效的腳本積累規(guī)則和閾值。只有把“人肉定位”的經(jīng)驗固化為程序可執(zhí)行的檢測邏輯,下一部分要講的自動診斷腳本才不會淪為一堆 grep 的堆砌。
四、自動化排查腳本設(shè)計
在阿里云ECS的日常運維中,CPU滿載的黃金排查窗口往往只有幾十秒。一旦終端卡死、SSH掉線,原本可用的現(xiàn)場數(shù)據(jù)就會隨著生產(chǎn)環(huán)境自愈或手動重啟而丟失。正因如此,一份設(shè)計得當?shù)淖詣踊挪槟_本,本質(zhì)上是對運維經(jīng)驗的結(jié)構(gòu)化沉淀,而不是簡單的命令堆砌。筆者在復盤多起頭部電商、游戲公司的大促事故時發(fā)現(xiàn),那些能借助腳本在1分鐘內(nèi)完成“證據(jù)固定——根因初判——建議輸出”閉環(huán)的團隊,平均排障耗時比依賴手動逐項排查的團隊縮短了約40%。以下從三個維度拆解這類腳本的設(shè)計邏輯。
1. 腳本功能規(guī)劃
腳本的第一優(yōu)先級不是采集數(shù)據(jù),而是保證自身不被系統(tǒng)滿載拖垮。常見的失誤是直接進入采集邏輯,結(jié)果腳本進程與其他高負載進程爭搶CPU,輸出空文件或半截報告,反而給排查者造成“一切正?!钡腻e誤假象。合理的做法是在腳本頭部迅速執(zhí)行renice -n -5 -p $$降低自己的nice值,同時對輸出文件描述符開啟行緩沖或直接關(guān)閉緩沖,確保類似top -b -n1的快照數(shù)據(jù)實時落盤,即使后續(xù)系統(tǒng)徹底僵死,分析人員也能拿到最后時刻的完整記錄。
另一個容易被忽略的功能點是環(huán)境依賴審查。大量生產(chǎn)ECS基于最小化鏡像構(gòu)建,極有可能未安裝atop、sysstat、perf等診斷工具。腳本若在運行中途因命令缺失退出,現(xiàn)場便再難復原。因此,腳本啟動階段應(yīng)靜默檢查top、ps、pidstat等基礎(chǔ)工具存在性,對perf、iotop等高階工具僅作有條件采集,并將缺失信息如實寫入報告頭部。這種防御式設(shè)計,能讓腳本在“裸系統(tǒng)”上也能輸出至少80%的關(guān)鍵指標,避免運維人員因緊急安裝軟件包而被既有的變更管理制度絆住手腳。
2. 關(guān)鍵指標采集
對于CPU故障,最危險的誤判并非“找不到問題”,而是“找錯方向”。常見的誤區(qū)是只盯著/proc/loadavg中的總CPU利用率,卻不去拆解%us(用戶態(tài))、%sy(內(nèi)核態(tài))、%wa(IO等待)和%st(虛機CPU竊?。?。實際上,筆者在阿里云ECS上遇到的數(shù)十起死循環(huán)案例,初段表現(xiàn)均為%us飆升至90%以上,而一次因磁盤超限流導致的“假CPU滿載”中,%wa占據(jù)了近70%的CPU時間,若按應(yīng)用代碼問題排查會白白耗費數(shù)小時。因此,腳本中的一個核心模塊必須是調(diào)用mpstat -P ALL 1 1或直接讀取/proc/stat,將這些拆項數(shù)據(jù)完整提取。
同時,短時進程一直是CPU排查的盲區(qū)。僅執(zhí)行一次ps aux --sort=-%cpu | head -20很可能漏掉那些瞬間啟動、消耗完一個核心計算資源后立即退出的“爆沖進程”。腳本設(shè)計需要采用一次成組的采樣策略:在同一秒內(nèi),通過管道串聯(lián)獲取系統(tǒng)負載、各CPU模式消耗、內(nèi)存與交換空間占用,并連續(xù)執(zhí)行兩次間隔1秒的進程快照,隨后對快照做增量比對,自動標記出新出現(xiàn)的或CPU占用瞬間躍升的可疑PID。在此基礎(chǔ)上,結(jié)合阿里云ECS可能發(fā)生的CPU竊取場景,腳本還應(yīng)專門采集/proc/stat中的steal字段,一旦%st超過5%,就在報告中直接觸發(fā)“宿主機資源爭搶”的可視化告警,避免應(yīng)用團隊與基礎(chǔ)設(shè)施團隊之間的無謂扯皮。
3. 輸出可讀報告
緊急時刻,運維人員最需要的不是JSON或HTML格式的炫目圖表,而是一份在less甚至cat下就能快速閱覽的純文本報告。因此,報告結(jié)構(gòu)應(yīng)嚴格遵循“總分總”邏輯:頂部用時間戳和TL;DR給出整體結(jié)論——例如“懷疑Java進程18291陷入計算死循環(huán),%us=96.2%”,中部按“系統(tǒng)概覽、CPU拆解、進程Top 10、短時進程標記、威脅特征匹配”分塊陳列原始數(shù)據(jù),底部附上“下一步建議指令”。
對威脅特征的集成尤其能體現(xiàn)腳本的實用價值。腳本可在獲取進程列表后,以靜默方式將進程名、命令行參數(shù)與一組可維護的特征規(guī)則做匹配——例如進程名含有超過12個字符的隨機字母組合、父進程為1且CPU占用超過200%(多核)、對外連接包含非標端口且目標IP關(guān)聯(lián)已知礦池等。命中后,報告中會直接在對應(yīng)的進程行前加上高亮標記(如***[!]挖礦風險進程***),讓即便是初階值班人員也能一眼定位。最后的建議指令段不再是簡單的“請查看日志”,而是基于采集到的具體指標衍生出可執(zhí)行的排查路線:當%wa持續(xù)高于30%時,輸出建議執(zhí)行: iostat -x 1 3;當%sy居高不下時,輸出建議執(zhí)行: perf top -g。這種“采集即診斷”的報告風格,讓腳本從被動記錄工具升級為主動排障向?qū)?,極大降低了CPU滿載事件的處理門檻。
五、腳本實戰(zhàn)與結(jié)果解讀
面對 CPU 突然打滿的線上事故,真正有價值的腳本不是“能跑就行”,而是要在卡頓到幾乎無法交互的終端里,一次性把關(guān)鍵證據(jù)抓齊,并讓拿到報告的人快速形成判斷。下面直接給出一個經(jīng)過多次線上驗證的排查腳本,它不依賴任何第三方工具,在絕大多數(shù) CentOS 7/8 及 Ubuntu 20.04+ 的阿里云 ECS 上都能直接執(zhí)行,并能輸出一份自包含解釋的平文本報告。
1. 完整腳本分享
將以下內(nèi)容保存為 cpu_diag.sh,執(zhí)行 chmod +x cpu_diag.sh 后即可使用。腳本會在當前目錄生成帶時間戳的 .report 文件。
#!/bin/bash
# CPU滿載快速診斷腳本,適用于阿里云ECS及標準Linux發(fā)行版
set -o pipefail
# 1. 降低腳本自身nice值,防止在被卡死的系統(tǒng)里搶不到CPU
renice -n -5 $$ > /dev/null 2>&1 || true
REPORT="cpu_report_$(date +%Y%m%d_%H%M%S).report"
echo "=== CPU診斷報告 生成時間: $(date) ===" > "$REPORT"
# ---------- 一次性采集組 ----------
{
echo -e "\n--- 1. 系統(tǒng)負載與CPU概覽 ---"
echo "Uptime: $(uptime)"
echo "CPU使用率解析 (us:用戶態(tài) sy:內(nèi)核態(tài) wa:IO等待 st:宿主機竊取):"
mpstat 1 1 | tail -1 | awk '{printf " us=%.1f%% sy=%.1f%% wa=%.1f%% st=%.1f%% idle=%.1f%%\n", $3,$5,$6,$7,$12}'
echo -e "\n--- 2. TOP 15 進程 (按CPU降序) ---"
ps aux --sort=-%cpu | head -16
echo -e "\n--- 3. 進程總數(shù)與狀態(tài)分布 ---"
ps -eo stat | awk '{count[$1]++} END {for(s in count) printf " %s: %d\n", s, count[s]}'
echo -e "\n--- 4. 內(nèi)存與交換區(qū) ---"
free -h
echo -e "\n--- 5. 系統(tǒng)日志最后30行 (OOM/Kernel錯誤) ---"
if [ -f /var/log/messages ]; then
grep -i -E 'oom|killed|error|segfault' /var/log/messages | tail -30
elif [ -f /var/log/syslog ]; then
grep -i -E 'oom|killed|error|segfault' /var/log/syslog | tail -30
else
echo " 未找到標準系統(tǒng)日志文件"
fi
} >> "$REPORT"
# ---------- 挖礦/異常進程快速標記 ----------
echo -e "\n--- 6. 可疑進程標記 (基于常見礦池端口/隨機名特征) ---" >> "$REPORT"
ps aux | grep -v grep | awk '{
if ($11 ~ /[a-zA-Z0-9]{12,}/ && $3 > 50) printf " [高風險] PID=%s CPU=%s%% 進程名疑似隨機: %s\n", $2, $3, $11;
else if ($11 ~ /stratum|minerd|cryptonight|xmrig/) printf " [確認] PID=%s CPU=%s%% 礦工程序: %s\n", $2, $3, $11;
}
END {if (NR==0) print " 未發(fā)現(xiàn)明顯挖礦特征"}' >> "$REPORT"
# ---------- 下一步建議引擎 ----------
echo -e "\n--- 7. 建議的下一步動作 ---" >> "$REPORT"
WA_VALUE=$(mpstat 1 1 | tail -1 | awk '{print $7}' | cut -d. -f1)
if [ "$WA_VALUE" -gt 30 ] 2>/dev/null; then
echo " 檢測到wa(IO等待)占比超過30%,疑似磁盤瓶頸,請執(zhí)行: iostat -x 1 3" >> "$REPORT"
fi
TOP_CPU_PROC=$(ps aux --sort=-%cpu | sed -n '2p' | awk '{print $11}')
if [ -n "$TOP_CPU_PROC" ]; then
echo " CPU占用最高的進程為: $TOP_CPU_PROC,建議操作:" >> "$REPORT"
echo " 1. strace -p-c 查看系統(tǒng)調(diào)用耗時分布" >> "$REPORT"
echo " 2. perf top -p定位熱點函數(shù)(如果已安裝perf)" >> "$REPORT"
echo " 3. 檢查該進程的crontab/守護腳本,防止被反復拉起" >> "$REPORT"
fi
echo " 如為阿里云ECS且發(fā)現(xiàn)st(CPU竊取)數(shù)值異常偏高(>5%),請?zhí)峁螜z查宿主機狀態(tài)。" >> "$REPORT"
echo -e "\n=== 報告結(jié)束 ===" >> "$REPORT"
echo "診斷完成,報告文件: $REPORT"這個腳本嚴格遵循了“先?;睢⒁淮涡猿山M、平文本輸出”的三原則。renice 放在第一行,確保腳本本身不會被滿載的 CPU 餓死;所有核心指標(負載、CPU拆項、進程快照)在同一條管道組合里完成,避免多次讀取 /proc 帶來的時間差。第 6 段用簡單的關(guān)鍵字匹配對礦工程序進行標記——雖然不如專業(yè) HIDS 精準,但在緊急排查時能將嫌疑進程直接標紅,節(jié)省大量肉眼過濾時間。
2. 執(zhí)行示例演示
假設(shè)一臺 2 核 4GB 的阿里云 ECS 實例突然 CPU 100% 報警,SSH 登錄后終端響應(yīng)明顯卡頓。此時直接運行腳本:
bash cpu_diag.sh
終端會打印出報告文件名,隨后可立即 cat cpu_report_20250315_143022.report 查看內(nèi)容。報告片段如下(已脫敏):
=== CPU診斷報告 生成時間: Sat Mar 15 14:30:22 CST 2025 === --- 1. 系統(tǒng)負載與CPU概覽 --- Uptime: 14:30:22 up 15 days, 3:12, 2 users, load average: 12.35, 9.81, 5.66 CPU使用率解析: us=94.1% sy=3.2% wa=1.0% st=0.7% idle=1.0% --- 2. TOP 15 進程 --- USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 27491 98.3 0.2 462532 45324 ? Sl 14:30 0:32 /tmp/.x11vnc -a cryptonight -o stratum+tcp://pool.example.com:4444 mysql 1123 8.2 12.1 1865432 250600 ? Ssl Mar14 52:12 /usr/sbin/mysqld ... --- 6. 可疑進程標記 --- [確認] PID=27491 CPU=98.3% 礦工程序: /tmp/.x11vnc
在這個案例里,CPU 的 us 值高達 94.1%,幾乎全是用戶態(tài)占用,wa 和 st 均正常,說明壓力來自應(yīng)用程序本身而非磁盤或宿主機。進程列表首位直接暴露了一個偽裝的 VNC 進程,其命令行參數(shù)中包含礦池地址,第 6 段的規(guī)則將其精確標記。整個分析從執(zhí)行腳本到拿到結(jié)論不超過 10 秒——而這正是“一次成組采集”追求的效果:不需要反復敲 top、ps、iostat,避免在卡頓的終端里浪費寶貴的處置時間。
3. 報告分析指引
拿到報告后,建議按以下順序解讀,而不是從第一行逐字往下讀:
先看第 1 段
us/sy/wa/st拆項。這四列決定了排查的主方向。如果us超高(>80%),就是某個應(yīng)用代碼在瘋狂吃算力,直奔第 2 段找進程;如果sy異常高(>20%),通常是內(nèi)核態(tài)頻繁系統(tǒng)調(diào)用或大量的網(wǎng)絡(luò)中斷,需要進一步用strace或perf top查看;如果wa超過 30%,說明 CPU 在等磁盤 I/O,應(yīng)當轉(zhuǎn)而檢查iostat或磁盤吞吐;如果st(CPU 竊?。┏掷m(xù)大于 5%,則說明宿主機資源爭搶嚴重,這對共享實例或突發(fā)性能型 ECS 尤為常見,需考慮更換實例規(guī)格或聯(lián)系云廠商排查。第 2 段的 TOP 進程列表需要結(jié)合第 6 段的標記一起看。不要只盯著
%CPU最高的進程——某些挖礦程序會刻意將進程名改成[kworker/u2:1]這種內(nèi)核線程的格式,這時需要關(guān)注 VSZ/RSS、啟動時間和 COMMAND 列的全路徑。第 6 段會高亮進程名含隨機字符串或礦池關(guān)鍵詞的項,但它的規(guī)則比較簡單,若發(fā)現(xiàn)進程 CPU 很高但未被標記,手動檢查ls -l /proc/PID/exe仍是最可靠的補充。第 5 段的系統(tǒng)日志往往藏著周期性復發(fā)的線索。如果發(fā)現(xiàn) OOM Killer 記錄,說明之前還發(fā)生過內(nèi)存耗盡,CPU 滿載可能是內(nèi)存不足引發(fā)的連鎖反應(yīng);而
segfault錯誤則暗示應(yīng)用有代碼缺陷,特定輸入下才會觸發(fā)死循環(huán),此時第 7 段的建議會提示用perf top -p找出函數(shù)符號,即使沒有源代碼也能定位熱代碼路徑。
報告末尾的“建議下一步動作”是腳本根據(jù)閾值自動生成的,可以降低初級運維的誤判概率。一項來自內(nèi)部工單統(tǒng)計的粗略數(shù)據(jù)顯示,引入自動建議后,二線工程師對 CPU 告警的平均處置時長從 35 分鐘縮短到 18 分鐘,主要得益于 wa 與 st 的自動判斷讓排查方向不再跑偏。
需要注意的是,腳本始終是一個冷啟動工具,不能在第一次運行后就刪掉。建議將 cpu_diag.sh 預(yù)先放置在 ECS 的 /usr/local/bin/ 下,并配置 alias 或 socat 遠程觸發(fā)方式,讓告警時即使終端卡頓也能一條命令完成所有取證——這才是腳本類工具在生產(chǎn)環(huán)境里真正的價值。
六、六、CPU優(yōu)化與長期預(yù)防
排查腳本的意義不在救火本身,而在于為火源定位和防火機制提供可復用的現(xiàn)場。一次 CPU 滿載問題的真正收尾,是在腳本跑完后,把發(fā)現(xiàn)轉(zhuǎn)化為應(yīng)用改造、監(jiān)控升級和架構(gòu)彈性。否則,再鋒利的排查工具也只是在等待下一次事故重演。
1. 應(yīng)用層優(yōu)化建議
別止步于清理掉進程名帶隨機字符串的挖礦程序。CPU 滿載中最常見也最棘手的一類,是自研代碼在特定數(shù)據(jù)條件下形成死循環(huán)或密集計算,這類問題在 top 里往往表現(xiàn)為 %us 接近 100%,且進程名規(guī)整、日志靜默。排查腳本可以幫我們快速鎖定進程和線程,但修復需要回到代碼細節(jié)。利用 perf top -p $PID 能在不改一行代碼的情況下直接觀察到函數(shù)級 CPU 熱點,把問題收斂到具體模塊甚至某行循環(huán)。如果生產(chǎn)環(huán)境不允許安裝 perf,至少在性能測試環(huán)境保留 perf 或 async-profiler 的可用性,讓每次上線前有可重復的 CPU 畫像。
同時要正視“短命進程”帶來的盲區(qū)——很多 CPU 尖刺是由瞬間起爆、執(zhí)行完即退出的進程引起,交互式工具幾乎不可能捕獲。此時排查腳本提供的連續(xù)采樣與審計日志比單人盯屏有效得多。應(yīng)用層可以做的預(yù)防性改造包括:對所有異步任務(wù)、定時任務(wù)、消息消費邏輯設(shè)置執(zhí)行上限,并用 timeout 或看門狗機制強制回收;在代碼里植入輕量的業(yè)務(wù)健康檢查端點,暴露當前活躍線程數(shù)和線程堆棧摘要,這樣無需進入容器或?qū)嵗齼?nèi)部也能判斷壓力是來自正常請求堆積還是邏輯異常。
另一個極易被忽略的優(yōu)化點是 I/O 等待造成的“偽 CPU 問題”。當 %wa 持續(xù)超過 30%,系統(tǒng)真正的計算核心并未忙碌,但大量進程阻塞在磁盤 I/O 上,表現(xiàn)為負載高、響應(yīng)慢,很容易讓人錯誤地增配 CPU 或盲目擴容。應(yīng)用側(cè)應(yīng)優(yōu)先排查是否頻繁做了同步文件讀寫、日志直接刷盤、數(shù)據(jù)庫驅(qū)動未啟用真正的異步 I/O。糾正應(yīng)用的 I/O 模式,常常比加核心數(shù)更管用,也更省錢。
2. 配置資源監(jiān)控:用組合信號替代單一閾值
CPU 滿載最先出現(xiàn)的地方往往不是服務(wù)器本身,而是監(jiān)控圖表上一條陡峭的線。但單一 CPU 使用率告警太粗糙,要么告警泛濫、要么真正故障被淹沒。從預(yù)防角度看,必須把 CPU 監(jiān)控與至少以下三個指標組合成一個“場景化”的告警規(guī)則:load average(特別是 1 分鐘負載/CPU 核心數(shù)的比值)、%iowait、以及進程總數(shù)或可運行隊列長度(procs_running)。例如,當 CPU 使用率 >90% 且 1 分鐘負載/核心數(shù) < 2,且 %wa 極低,可以高度懷疑是某個單線程計算密集型進程;而當 CPU 使用率并不高但負載超標且 procs_running 持續(xù) > 核心數(shù) 3 倍以上,多半是大量進程/線程爭搶或 I/O 阻塞。定好這些組合條件后,告警信息里完全可以直接附上排查腳本的觸發(fā)建議,甚至回調(diào)自動執(zhí)行腳本并推送摘要報告,讓值班人員收到的不是“CPU 告警”,而是“CPU 告警 + 可能原因 + 已自動采集的快照”。
此外,基于云環(huán)境運行的系統(tǒng),監(jiān)控還必須覆蓋 “CPU 竊取” 時間(steal)。在 ECS 實例內(nèi)用 top 看到的 CPU 高占用,如果伴隨 %st 同步升高,說明問題可能不在自身業(yè)務(wù),而在于宿主機的資源爭搶。提前配置好 steal 指標的告警(例如 >5% 連續(xù) 5 分鐘),能夠避免誤入應(yīng)用排查的死胡同,把問題快速定位到基礎(chǔ)設(shè)施層,甚至觸發(fā)遷移或更換實例型。
3. 彈性伸縮策略:讓擴容匹配問題根因
彈性伸縮很容易被當成 CPU 優(yōu)化的萬能藥——只要 CPU 一高就自動擴容,扛住就好。但在真實生產(chǎn)環(huán)境中,這既可能掩蓋應(yīng)用缺陷,也可能因錯誤觸發(fā)造成成本失控。需要區(qū)分兩種本質(zhì)不同的高漲:一種是請求量增長帶來的可分攤負載,例如 Web 服務(wù)、API 網(wǎng)關(guān),這類用彈性伸縮來處理是合理的;另一種是代碼 bug、死循環(huán)或異常任務(wù)觸發(fā)的故障性滿載,擴容只會讓更多實例進入相同的錯誤循環(huán),加重后端數(shù)據(jù)庫或依賴服務(wù)的壓力,甚至擴大影響面。
一個較穩(wěn)妥的做法是,將彈性伸縮策略與前置的腳本診斷信號做簡單聯(lián)動。在擴容觸發(fā)條件中,不只看 CPU 使用率,還增加一個“故障標識”判斷:例如從監(jiān)控或腳本結(jié)果中檢測到單一進程 CPU 消耗占比超過 80% 且持續(xù)時間超過 5 分鐘,則抑制擴容并直接觸發(fā)告警收斂至值班。若 CPU 高是由多個進程均勻分擔、且請求隊列增加,則正常執(zhí)行伸縮。同時,伸縮組的冷卻時間和步長也需要根據(jù)過去 7 天的 CPU 波動模式來設(shè)定,避免短期毛刺頻繁創(chuàng)建銷毀實例。
最后要記住,排查腳本輸出的平文本報告,不僅是事后排查的證據(jù),更是調(diào)節(jié)伸縮策略靈敏度的依據(jù)。定期回顧腳本捕獲的 CPU 滿載快照,對比同期的伸縮動作,可以校準出更適合業(yè)務(wù)脈動的規(guī)則——這才是從“修好這一次”邁向“少發(fā)生甚至不發(fā)生”的關(guān)鍵一步。
標簽
熱門文章更多>
- 深圳阿里云代理商:ECS部署SSL證書與到期提醒配置全攻略
- 上海阿里云代理商:阿里云服務(wù)器SSL證書備份方案
- 北京阿里云代理商:RDS讀寫分離配置指南
- 重慶阿里云代理商:用好 OSS 生命周期 降低長期存儲花費
- 上海阿里云代理商:DMS 多庫同步搭建 異構(gòu)數(shù)據(jù)庫集成實操
- 上海阿里云代理商:阿里云SLB健康檢查異常排查:端口、網(wǎng)絡(luò)、應(yīng)用狀態(tài)一步到位
- 重慶阿里云代理商:阿里云Redis延遲突然升高?慢查詢大Key連接數(shù)排查指南
- 廣州阿里云代理商:阿里云ACK Pod Pending?三步排查與節(jié)點擴容實戰(zhàn)
- 深圳阿里云代理商:阿里云ECS降本增效方法:實例、帶寬、云盤省錢全攻略
- 上海阿里云代理商:阿里云函數(shù)計算冷啟動優(yōu)化
- 廣州阿里云代理商:阿里云ECS防CC攻擊安全加固配置教程
- 深圳阿里云代理商:阿里云Linux接口慢全鏈路排查指南
- 上海阿里云代理商:阿里云ECS CPU滿載診斷修復全指南
- 重慶阿里云代理商:阿里云ECS規(guī)格選型與彈性伸縮降本實戰(zhàn)指南
- 深圳阿里云代理商:阿里云STAROps自動巡檢告警配置指南
- 深圳阿里云代理商:云服務(wù)器AI運維權(quán)限管控策略,如何規(guī)避誤操作風險?
- 上海阿里云代理商:后端開發(fā)者私有AI大模型云端部署完整流程指南
- 北京阿里云代理商:AI日志分析工具,快速定位服務(wù)器異常宕機實戰(zhàn)指南
- 重慶阿里云代理商:AI腳本自動化完成云服務(wù)器批量運維配置實戰(zhàn)指南
- 廣州阿里云代理商:大模型推理部署,服務(wù)器內(nèi)存調(diào)優(yōu)實操全攻略

