背景與問題
在 Linux 系統(tǒng)的日常運維中,監(jiān)控進程資源使用情況是最頻繁的工作之一。當(dāng)服務(wù)器 CPU 突然飆高、內(nèi)存告警、或者業(yè)務(wù)響應(yīng)變慢時,運維工程師首先要做的事情就是查看系統(tǒng)資源使用狀況。top、ps、free這三個命令幾乎是每個運維人員每天都要敲幾十遍的工具。
然而,很多初中級運維人員對這些命令的了解僅限于最基本的用法。看到top輸出滿屏的數(shù)據(jù),不知道該關(guān)注哪幾列;執(zhí)行ps aux輸出一大堆進程,不知道如何過濾出關(guān)鍵信息;free顯示的內(nèi)存數(shù)值和實際感受對不上,不知道 buffers 和 cache 有什么區(qū)別。本文將從系統(tǒng)原理出發(fā),深入講解這三個命令的完整功能和正確查看方法,讓運維人員能夠真正讀懂系統(tǒng)資源狀態(tài),快速定位性能瓶頸。
1 top 命令詳解
1.1 top 的基本運行原理
top是 Linux 下最常用的實時系統(tǒng)監(jiān)控工具,它周期性地刷新顯示系統(tǒng)進程和資源使用信息。理解top的運行機制有助于更好地使用它。
top默認(rèn)每 3 秒刷新一次數(shù)據(jù),可以通過-d參數(shù)調(diào)整刷新間隔。在交互式界面中,可以按s鍵輸入新的刷新間隔,按q鍵退出。
top的數(shù)據(jù)來源主要是/proc文件系統(tǒng)。它讀取/proc/stat獲取 CPU 統(tǒng)計信息,讀取/proc/meminfo獲取內(nèi)存信息,讀取/proc/*/stat獲取各個進程的 CPU 和內(nèi)存使用情況。因此,top本身也是一個普通進程,它的資源消耗(尤其是 CPU)會計入系統(tǒng)統(tǒng)計。
top在啟動時會嘗試確定 CPU 核心數(shù),并根據(jù)核心數(shù)決定默認(rèn)的顯示模式。在多核系統(tǒng)中,按1可以展開顯示每個核心的單獨使用率,這是排查 CPU 負(fù)載分布不均問題時的關(guān)鍵操作。
1.2 top 輸出字段解析
執(zhí)行top后,屏幕分為兩部分:頂部是系統(tǒng)整體資源使用情況的匯總區(qū),下方是進程列表。理解每個字段的含義是正確分析系統(tǒng)狀態(tài)的前提。
1.2.1 匯總區(qū)字段說明
top頂部匯總區(qū)的典型輸出如下:
top - 1415 up 45 days, 3:22, 2 users, load average: 1.25, 0.98, 0.85 Tasks: 287 total, 3 running, 284 sleeping, 0 stopped, 0 zombie %Cpu(s): 15.3 us, 2.1 sy, 0.0 ni, 81.2 id, 1.2 wa, 0.0 hi, 0.2 si, 0.0 st MiB Mem : 32768.0 total, 8192.4 free, 16384.0 used, 8191.6 buff/cache MiB Swap: 8192.0 total, 8192.0 free, 0.0 used, 2097152.0 avail Mem
第一行顯示系統(tǒng)運行時間和負(fù)載均值。up后面是系統(tǒng)運行時間(45 天 3 小時 22 分);load average后面三個數(shù)字分別表示 1 分鐘、5 分鐘、15 分鐘的平均負(fù)載。負(fù)載均值表示系統(tǒng)中處于就緒狀態(tài)(等待 CPU 或正在運行)的平均進程數(shù)量。在單核系統(tǒng)上,load average 為 1.0 表示 CPU 滿負(fù)荷;在多核系統(tǒng)上,滿負(fù)荷的 load average 等于 CPU 核心數(shù)。4 核 CPU 的 load average 為 4.0 表示 CPU 完全飽和。
理解負(fù)載均值需要結(jié)合 CPU 使用率一起看。如果 CPU 使用率很低但負(fù)載均值很高,說明進程可能在等待 I/O(磁盤或網(wǎng)絡(luò));如果 CPU 使用率很高且負(fù)載均值也很高,說明 CPU 是瓶頸。
第二行顯示進程狀態(tài)統(tǒng)計。total是進程總數(shù);running是正在運行的進程數(shù)(包含正在使用 CPU 和等待 CPU 的進程);sleeping是處于睡眠狀態(tài)的進程數(shù)(通常是等待事件);stopped是被暫停的進程數(shù)(收到 SIGSTOP 信號);zombie是僵尸進程數(shù)(已終止但父進程未回收)。
第三行是 CPU 使用率細(xì)分,這是排查 CPU 問題的核心數(shù)據(jù)。us(user space)是用戶空間進程消耗的 CPU 時間百分比,是最常見的 CPU 使用來源;sy(system)是內(nèi)核空間消耗的 CPU 時間,系統(tǒng)調(diào)用和內(nèi)核內(nèi)部操作會計入此處;ni(nice)是低優(yōu)先級用戶空間進程消耗的 CPU 時間;id(idle)是空閑時間,100% 表示 CPU 完全空閑;wa(wait)是 CPU 等待 I/O 完成的時間比例,如果這個值很高(比如超過 20%),說明進程在等待磁盤或網(wǎng)絡(luò) I/O;hi(hardware interrupt)是硬件中斷處理消耗的 CPU 時間;si(software interrupt)是軟件中斷消耗的 CPU 時間;st(steal)是虛擬化環(huán)境中被其他虛擬機搶走的 CPU 時間。
第四行和第五行是內(nèi)存統(tǒng)計。total是總內(nèi)存;free是真正空閑的內(nèi)存;used是已使用的內(nèi)存;buff/cache是被 buffers 和 cache 占用的內(nèi)存,它們會在應(yīng)用程序需要時自動釋放;avail Mem是可用的內(nèi)存(包括已分配的 cache 可以釋放的部分);Swap行顯示交換分區(qū)使用情況,used 不為 0 說明物理內(nèi)存不足。
1.2.2 進程列表字段說明
top默認(rèn)按 CPU 使用率排序顯示進程列表,每一行代表一個進程,主要字段包括:
PID是進程 ID,每個運行中的進程都有唯一的 PID。USER是進程所有者的用戶名。PR是進程的調(diào)度優(yōu)先級,rt 表示實時進程,數(shù)值越小優(yōu)先級越高。NI是進程的 nice 值,范圍是 -20 到 19,數(shù)值越小優(yōu)先級越高。VIRT是進程使用的虛擬內(nèi)存總量,包括代碼、數(shù)據(jù)、共享庫、已交換出去的內(nèi)存等。RES是進程使用的物理內(nèi)存(Resident Set Size),這是實際占用的 RAM 大小。SHR是進程使用的共享內(nèi)存大小。S是進程狀態(tài):D=不可中斷的睡眠,R=運行,S=睡眠,T=跟蹤/暫停,Z=僵尸。
%CPU是進程使用的 CPU 百分比,在多核系統(tǒng)上,一個進程使用一個核心的 100% 會顯示為 12.5%(8 核系統(tǒng))。%MEM是進程使用的物理內(nèi)存占總量的百分比。TIME+是進程累計使用的 CPU 時間,格式為分:秒。COMMAND是啟動進程的命令名。
1.3 top 交互式操作
top提供了豐富的交互式操作,熟練使用這些快捷鍵可以大大提高排查效率:
按h或?顯示幫助菜單。按q退出。按1展開或折疊 CPU 核心數(shù)顯示。按s修改刷新間隔。按d修改刷新間隔(與 s 相同)。按z切換彩色顯示,提高可讀性。按x高亮排序列。按b高亮運行中的進程(running)。
按M按內(nèi)存使用率排序。按P按 CPU 使用率排序(默認(rèn))。按T按累計 CPU 時間排序。按R反向排序(升序變降序)。
按u再輸入用戶名,只顯示指定用戶的進程。按i切換顯示空閑進程。按n設(shè)置最大顯示進程數(shù)。按c顯示完整命令行(包括參數(shù))。
按k再輸入 PID,殺掉指定進程(需要確認(rèn))。按r重新設(shè)置進程優(yōu)先級(renice)。
按W保存當(dāng)前配置到~/.toprc,下次啟動時自動應(yīng)用。
1.4 top 的批量模式和腳本使用
在自動化監(jiān)控腳本中,需要使用top的批量模式獲取數(shù)據(jù):
# 批量模式:執(zhí)行一次后退出,每行一個進程 top -b -n 1 # 指定刷新次數(shù)和間隔 top -b -n 5 -d 1 > top_output.txt # 只顯示指定用戶的進程 top -b -n 1 -u www-data # 只顯示指定 PID 的進程 top -b -n 1 -p 1234 # 輸出指定的字段 top -b -n 1 -o %CPU -e # 結(jié)合 head 提取匯總信息和前 20 個進程 top -b -n 1 -o %CPU | head -30
在腳本中提取特定字段需要使用awk:
# 獲取當(dāng)前 CPU 使用率
top -b -n 1 | grep"Cpu(s)"| awk'{print $2}'| cut -d'%'-f1
# 獲取內(nèi)存使用率
top -b -n 1 | grep"Mem"| awk'{print $3}'| cut -d'.'-f1
# 獲取 top 5 CPU 占用進程
top -b -n 1 -o %CPU | head -12 | tail -6
# 獲取指定進程的 CPU 和內(nèi)存使用率
pid=1234
top -b -n 1 -p$pid| tail -1 | awk'{print $9, $10}'
1.5 top 的配置保存
top的顯示配置可以通過交互式操作調(diào)整后保存:
# 在 top 交互界面中按 W 保存配置 # 配置文件位于 ~/.toprc # 示例:查看現(xiàn)有配置 cat ~/.toprc
保存的配置包括刷新間隔、顯示字段、排序方式等。下次啟動top時會自動加載這些設(shè)置。
2 ps 命令詳解
2.1 ps 命令的三種語法風(fēng)格
ps命令支持三種不同的語法風(fēng)格,這是很多初學(xué)者感到困惑的地方。POSIX 標(biāo)準(zhǔn)語法風(fēng)格使用單個字母選項,前面加短橫線;BSD 風(fēng)格選項不需要短橫線;GNU 長選項風(fēng)格使用兩個短橫線。
三種風(fēng)格可以混合使用,但需要注意兼容性:
# POSIX 風(fēng)格 ps -eo pid,user,%cpu,%mem,comm # BSD 風(fēng)格(不需要短橫線) ps aux # GNU 長選項風(fēng)格 ps --pid 1234 --format pid,user,%cpu
ps aux是 BSD 風(fēng)格最常用的組合:a顯示所有終端上的進程(包括其他用戶的進程);x顯示沒有控制終端的進程(守護進程);u顯示面向用戶的格式(包含用戶名、CPU、內(nèi)存等詳細(xì)信息)。
2.2 ps 輸出字段詳解
ps aux的輸出包含多個字段,每個字段都提供進程的重要信息:
ps aux # USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND # root 1234 0.1 0.5 123456 7890 ? Ss Jan15 2:34 /usr/sbin/sshd -D
USER是進程所有者的用戶名。PID是進程 ID。%CPU是 CPU 使用百分比。%MEM是內(nèi)存使用百分比(相對于物理內(nèi)存)。VSZ是虛擬內(nèi)存大小(單位 KB),包括所有映射的內(nèi)存。RSS是實際使用的物理內(nèi)存大?。≧esident Set Size),不包括已交換出去的內(nèi)存。TTY是進程關(guān)聯(lián)的終端,?表示沒有控制終端(通常是守護進程)。STAT或STATE是進程狀態(tài)。START是進程啟動時間。TIME是累計 CPU 時間。COMMAND是命令名或命令行。
2.3 ps 常用命令組合
ps命令的強大之處在于可以根據(jù)不同需求組合各種選項和過濾器:
# 查看所有進程,顯示完整格式 ps -ef ps aux # 查看特定用戶的進程 ps -u www-data ps -u www-data -f # 查看特定 PID 的進程 ps -p 1234 ps -p"1234 5678 9012" # 查看特定命令的進程 ps -C nginx ps -C nginx -f # 查看進程的父子關(guān)系(進程樹) ps -ef --forest ps aux --forest # 查看命令的完整參數(shù) ps -ef | grep nginx ps -eo pid,args # 查看特定進程的線程 ps -L -p 1234 ps -eLf | grep nginx # 查看進程的文件描述符(需要 root) ls -la /proc/1234/fd # 查看進程的環(huán)境變量(需要 root) cat /proc/1234/environ | tr'?'' '
2.4 ps 格式化輸出
ps的-o選項允許自定義輸出字段,這是編寫監(jiān)控腳本時的常用功能:
# 基本語法:-o field1,field2,... ps -o pid,user,%cpu,%mem,etime,cmd # 常用字段代碼: # pid - 進程 ID # user - 用戶名 # %cpu - CPU 使用率 # %mem - 內(nèi)存使用率 # vsz - 虛擬內(nèi)存大小 # rss - 物理內(nèi)存大小 # pmem - 內(nèi)存使用百分比(精確) # pcpu - CPU 使用百分比(精確) # etime - 進程運行時間 # time - 累計 CPU 時間 # cmd - 命令(不帶參數(shù)) # args - 命令(帶完整參數(shù)) # comm - 命令名(不含路徑) # tty - 控制終端 # stat - 進程狀態(tài) # nice - nice 值 # priority - 調(diào)度優(yōu)先級 # 示例:自定義輸出格式 ps -eo pid,user,comm,%cpu,%mem,etime,state # 添加列標(biāo)題 ps -eo pid,user,comm,%cpu,%mem,etime,state --headers # 只顯示指定字段 ps -eo pid,args --no-headers
2.5 ps 與其他命令的結(jié)合使用
在日常運維中,ps經(jīng)常與其他命令結(jié)合使用來完成復(fù)雜查詢:
# 查找 CPU 使用率最高的前 10 個進程 ps aux --sort=-%cpu | head -11 # 查找內(nèi)存使用率最高的前 10 個進程 ps aux --sort=-%mem | head -11 # 查找特定用戶的所有進程 ps -U www-data -u www-data u # 查找僵尸進程 ps aux | grep Z # 查找占用內(nèi)存最多的 Java 進程 ps aux | grep java | sort -k4 -rn | head -5 # 統(tǒng)計某命令的進程數(shù) ps -C nginx | wc -l pgrep nginx | wc -l # 查看進程的啟動命令和環(huán)境 ps eww -p 1234 # 查找孤進程(父進程已終止) ps -ef | awk'$3 == 1 {print}'
2.6 pgrep 和 pkill
pgrep和pkill是專門用于進程查找和管理的工具,是對ps的便捷封裝:
# 查找匹配條件的進程 PID pgrep nginx pgrep -u www-data nginx # 查找進程并顯示詳細(xì)信息 pgrep -a nginx # 查找進程并顯示完整命令行 pgrep -f"nginx -g daemon" # 查找指定用戶的進程數(shù) pgrep -U www-data | wc -l # 殺死匹配條件的進程(默認(rèn)發(fā)送 SIGTERM) pkill nginx # 強制殺死匹配條件的進程 pkill -9 nginx # 只殺死指定用戶的進程 pkill -u www-data nginx # 殺死匹配條件并顯示被殺死的進程 pkill -ef"python script.py"
3 free 命令詳解
3.1 free 的輸出解讀
free命令顯示系統(tǒng)內(nèi)存使用情況的匯總信息,是排查內(nèi)存問題的首選工具:
free -h
輸出示例:
total used free shared buff/cache available
Mem: 32Gi 12.5Gi 8.2Gi 128Mi 11.3Gi 18.7Gi
Swap: 8.0Gi 0B 8.0Gi
total是物理內(nèi)存的總?cè)萘俊sed是已使用的內(nèi)存量。free是完全空閑的內(nèi)存量。shared是被tmpfs文件系統(tǒng)使用的內(nèi)存(通常很?。?。buff/cache是被 buffers 和 cache 占用的內(nèi)存,它們是內(nèi)核用來緩存磁盤數(shù)據(jù)的,會在應(yīng)用程序需要時自動釋放。available是應(yīng)用程序?qū)嶋H可以使用的內(nèi)存(包括已分配的 cache 可以釋放的部分),這是判斷系統(tǒng)是否缺內(nèi)存的最準(zhǔn)確指標(biāo)。
3.2 buffers 與 cache 的區(qū)別
理解 buffers 和 cache 的區(qū)別對于正確判斷內(nèi)存狀態(tài)至關(guān)重要。
Cache(頁面緩存)是內(nèi)核為了加速文件讀取而緩存的磁盤數(shù)據(jù)。當(dāng)應(yīng)用程序讀取文件時,內(nèi)核會把讀取的數(shù)據(jù)緩存在 RAM 中,下次讀取同一文件時可以直接從內(nèi)存返回,避免磁盤 I/O。寫入文件時,內(nèi)核通常先寫入 cache,然后異步刷回磁盤。Cache 包括 page cache、dentries、inodes 等。
Buffers(塊設(shè)備緩存)是用于緩存原始磁盤塊的內(nèi)存,與具體文件無關(guān),主要用于塊設(shè)備(如磁盤)的元數(shù)據(jù)緩存。在現(xiàn)代 Linux 內(nèi)核中,buffers 和 cache 的界限已經(jīng)模糊,它們被統(tǒng)一管理在buff/cache這一項中。
關(guān)鍵理解:buffers 和 cache 占用的內(nèi)存不是"丟失"的內(nèi)存,而是內(nèi)核為了提高 I/O 性能而主動使用的緩存。當(dāng)應(yīng)用程序需要更多內(nèi)存時,內(nèi)核會自動釋放這些緩存,將內(nèi)存分配給應(yīng)用程序。這個過程不需要人工干預(yù),也不應(yīng)該通過人工釋放 cache 來"解決"內(nèi)存問題。
3.3 free 命令的選項
# 以人類可讀的格式顯示(自動選擇 KB/MB/GB) free -h # 以字節(jié)為單位顯示 free -b # 以 KB 為單位顯示 free -k # 以 MB 為單位顯示 free -m # 以 GB 為單位顯示 free -g # 顯示低內(nèi)存和高內(nèi)存的統(tǒng)計(廢棄選項,僅保留兼容性) free -l # 持續(xù)顯示,每隔 N 秒刷新一次 free -s 5 free -s 5 -c 10 # 刷新 10 次后退出 # 顯示總計行 free -t # 不顯示緩存行 free -o
3.4 理解 available 與 free 的區(qū)別
available是MemAvailable的值,這是內(nèi)核 3.14 版本引入的字段,它更準(zhǔn)確地反映了應(yīng)用程序?qū)嶋H可用的內(nèi)存數(shù)量。free只是完全空閑的內(nèi)存,但available包含了可以被釋放的 cache。
例如,一個 32GB 內(nèi)存的系統(tǒng),free顯示 8GB,buff/cache顯示 11GB。表面上看 free 只有 8GB,但實際上應(yīng)用程序還可以使用約 18.7GB(free + 可釋放的 cache)。如果僅看free字段判斷內(nèi)存夠不夠用,會得出錯誤的結(jié)論。
3.5 交換空間(Swap)監(jiān)控
Swap 的使用情況是判斷物理內(nèi)存是否充足的重要指標(biāo):
# 查看 swap 使用情況
free -h
swapon -s
# 查看詳細(xì)的 swap 使用
cat /proc/swaps
# 關(guān)閉所有 swap(不推薦,可能導(dǎo)致 OOM)
swapoff -a
# 開啟所有 swap
swapon -a
# 查看哪個進程使用了 swap
forfin/proc/*/status;doawk'/VmSwap/{s+=$2}/Name/{n=$2}END{if(s>0)print n,s}'$f;done| sort -k2 -rn | head
正常的 Swap 使用應(yīng)該是 0 或接近 0。如果 Swap 使用量持續(xù)很高(比如幾 GB),說明物理內(nèi)存不足,操作系統(tǒng)在把不活躍的內(nèi)存頁交換到磁盤,這會嚴(yán)重影響性能。
如果發(fā)現(xiàn)系統(tǒng)頻繁使用 swap,應(yīng)該:檢查是否有內(nèi)存泄漏的進程;調(diào)整應(yīng)用程序的內(nèi)存使用配置;增加物理內(nèi)存;優(yōu)化應(yīng)用程序的內(nèi)存使用。
3.6 /proc/meminfo 詳解
free命令的數(shù)據(jù)來源是/proc/meminfo,深入理解這個文件可以更好地理解內(nèi)存管理:
cat /proc/meminfo
關(guān)鍵字段說明:
MemTotal是可用的物理內(nèi)存總量。MemFree是完全空閑的內(nèi)存。MemAvailable是應(yīng)用程序可用的內(nèi)存估計值。Buffers是用于塊設(shè)備元數(shù)據(jù)的內(nèi)存。Cached是用于文件內(nèi)容緩存的內(nèi)存。SwapCached是已經(jīng)存在于 swap 空間但被換入到內(nèi)存的頁面(避免二次 I/O)。Active是活躍的內(nèi)存(最近使用過且不立即釋放)。Inactive是不活躍的內(nèi)存(可以被回收)。Shmem是共享內(nèi)存(tmpfs)。SReclaimable是可回收的 slab 內(nèi)存。SUnreclaim是不可回收的 slab 內(nèi)存。Mlocked是被mlock()鎖定的內(nèi)存。
判斷內(nèi)存是否緊缺應(yīng)該看MemAvailable而不是MemFree。判斷是否需要增加內(nèi)存應(yīng)該看 swap 使用情況和ActivevsInactive的比例。
4 綜合排查場景
4.1 場景一:CPU 使用率高排查
當(dāng)發(fā)現(xiàn) CPU 使用率持續(xù)很高時,按以下步驟排查:
第一步,確認(rèn)是全局 CPU 高還是某個核心高:
# 展開查看每個核心的使用率 top # 按 1
如果只有一兩個核心高,說明是單線程程序瓶頸;如果所有核心都高,說明是多個進程或整體負(fù)載高。
第二步,確認(rèn)是用戶空間還是內(nèi)核空間消耗高:
# 查看 CPU 使用率細(xì)分 top # 查看 us(用戶空間)和 sy(系統(tǒng)空間)的比例
us高通常是應(yīng)用程序的計算負(fù)載高;sy高通常是系統(tǒng)調(diào)用頻繁或 I/O 操作多。
第三步,找到消耗 CPU 的具體進程:
# 按 CPU 使用率排序 ps aux --sort=-%cpu | head -20 # 查看具體進程的線程 ps -p $(pgrep -f nginx) -L -o pid,tid,%cpu,cmd
第四步,分析進程行為:
# 查看進程的打開文件 ls -la /proc/1234/fd # 查看進程的 syscall strace -p 1234 2>&1 | head -50 # 查看進程的堆棧 pstack 1234
4.2 場景二:內(nèi)存使用率高排查
當(dāng)發(fā)現(xiàn)內(nèi)存使用率持續(xù)很高時:
第一步,確認(rèn)是進程使用還是 cache 使用:
free -h # 查看 buff/cache 是否很高
如果buff/cache很高但available仍然充足,說明只是緩存,不算真正的內(nèi)存緊缺。
第二步,找到消耗內(nèi)存的具體進程:
# 按內(nèi)存使用率排序 ps aux --sort=-%mem | head -20 # 查看進程詳細(xì)信息 ps -eo pid,user,%mem,%cpu,vsz,rss,cmd --sort=-%mem | head -20
第三步,分析進程的內(nèi)存使用:
# 查看進程的內(nèi)存映射 pmap -x 1234 # 查看進程的詳細(xì)內(nèi)存狀態(tài) cat /proc/1234/status | grep -E"Vm|Rss|Pid"
4.3 場景三:Java 進程內(nèi)存問題排查
Java 進程(Tomcat、Spring Boot 等)有特殊的內(nèi)存模型,需要專門分析:
# 查看 Java 進程的內(nèi)存使用(RSS) ps aux | grep java # 查看 JVM 堆內(nèi)存使用(需要 jstat 或 jcmd) jstat -gc 1234 # 查看 JVM 內(nèi)存池 jcmd 1234 GC.heap_info # 分析 heap dump(需要先生成 dump) jmap -dump:format=b,file=heap.bin 1234
4.4 場景四:進程僵死(hung)排查
當(dāng)進程不響應(yīng)請求但不消耗 CPU 時:
# 查看進程狀態(tài)
ps -eo pid,stat,args --sort=stat| grep D
# 查看 D 狀態(tài)進程(不可中斷的睡眠)
ps aux | awk'$8~/D/ {print}'
# 查看進程的等待事件
cat /proc/1234/wchan
# 查看進程的堆棧
cat /proc/1234/stack
D 狀態(tài)(Uninterruptible Sleep)通常表示進程在等待 I/O(磁盤、網(wǎng)絡(luò))或內(nèi)核事件。這種狀態(tài)不應(yīng)該持續(xù)很久,如果持續(xù)很久(比如幾分鐘),可能是 I/O 子系統(tǒng)出了問題。
4.5 場景五:僵尸進程排查
僵尸進程是已終止但父進程未回收的進程:
# 查找僵尸進程
ps aux | awk'$8=="Z" {print}'
# 查看僵尸進程的父進程
ps -ef | awk'$3==1234 {print}'# 1234 是僵尸進程的 PID
# 找到所有僵尸進程及其父進程
ps -eo pid,stat,ppid,args | awk'$2~/Z/ {print}'
# 殺死僵尸進程的父進程(謹(jǐn)慎操作)
kill-9 <父進程PID>
僵尸進程本身不消耗資源(已釋放所有內(nèi)存),但會占用 PID 和進程表空間。如果系統(tǒng)中有很多僵尸進程,可能是應(yīng)用程序有 bug 導(dǎo)致父進程沒有正確調(diào)用wait()回收子進程。
5 自動化監(jiān)控腳本示例
5.1 系統(tǒng)資源監(jiān)控腳本
#!/bin/bash
# system_monitor.sh - 系統(tǒng)資源監(jiān)控腳本
LOG_DIR="/var/log/monitor"
DATE=$(date +%Y%m%d)
LOG_FILE="${LOG_DIR}/monitor_${DATE}.log"
# 創(chuàng)建日志目錄
mkdir -p$LOG_DIR
# 記錄時間戳
echo"=== System Monitor Report:$(date)===">>$LOG_FILE
# CPU 使用情況
echo"">>$LOG_FILE
echo"--- CPU ---">>$LOG_FILE
top -bn1 | grep"Cpu(s)">>$LOG_FILE
echo"Top 5 CPU processes:">>$LOG_FILE
ps aux --sort=-%cpu | head -6 >>$LOG_FILE
# 內(nèi)存使用情況
echo"">>$LOG_FILE
echo"--- Memory ---">>$LOG_FILE
free -h >>$LOG_FILE
echo"Top 5 Memory processes:">>$LOG_FILE
ps aux --sort=-%mem | head -6 >>$LOG_FILE
# 磁盤 I/O 情況
echo"">>$LOG_FILE
echo"--- Disk I/O ---">>$LOG_FILE
iostat -x 1 1 2>/dev/null >>$LOG_FILE||echo"iostat not available">>$LOG_FILE
# 網(wǎng)絡(luò)連接情況
echo"">>$LOG_FILE
echo"--- Network Connections ---">>$LOG_FILE
netstat -an | awk'/^tcp/ {s[$NF]++} END {for(k in s) print k, s[k]}'>>$LOG_FILE
# Load Average
echo"">>$LOG_FILE
echo"--- Load Average ---">>$LOG_FILE
uptime >>$LOG_FILE
echo"Log saved to:$LOG_FILE"
5.2 告警腳本
#!/bin/bash
# alert.sh - 資源告警腳本
# 告警閾值
CPU_THRESHOLD=80
MEM_THRESHOLD=85
DISK_THRESHOLD=90
# 檢查 CPU
CPU_USAGE=$(top -bn1 | grep"Cpu(s)"| awk'{print $2}'| cut -d'%'-f1)
if(( $(echo"$CPU_USAGE>$CPU_THRESHOLD"| bc -l) ));then
echo"ALERT: CPU usage is${CPU_USAGE}% (threshold:${CPU_THRESHOLD}%)"
fi
# 檢查內(nèi)存
MEM_USAGE=$(free | grep Mem | awk'{printf "%.0f", $3/$2 * 100}')
if["$MEM_USAGE"-gt"$MEM_THRESHOLD"];then
echo"ALERT: Memory usage is${MEM_USAGE}% (threshold:${MEM_THRESHOLD}%)"
fi
# 檢查磁盤
DISK_USAGE=$(df -h / | awk'NR==2 {print $5}'| cut -d'%'-f1)
if["$DISK_USAGE"-gt"$DISK_THRESHOLD"];then
echo"ALERT: Disk usage is${DISK_USAGE}% (threshold:${DISK_THRESHOLD}%)"
fi
# 檢查 swap
SWAP_USED=$(free | grep Swap | awk'{print $3}')
if["$SWAP_USED"-gt 0 ];then
echo"WARNING: Swap is being used (${SWAP_USED}KB)"
fi
5.3 進程分析腳本
#!/bin/bash # process_analyzer.sh - 進程資源分析腳本 TARGET_PID=$1 if[ -z"$TARGET_PID"];then echo"Usage:$0" exit1 fi if[ ! -d"/proc/$TARGET_PID"];then echo"Process$TARGET_PIDnot found" exit1 fi echo"=== Process Analysis: PID$TARGET_PID===" # 基本信息 echo"" echo"--- Basic Info ---" ps -p$TARGET_PID-o pid,ppid,user,%cpu,%mem,time,cmd # 內(nèi)存詳情 echo"" echo"--- Memory Details ---" pmap -x$TARGET_PID| tail -1 # 線程數(shù) echo"" echo"--- Thread Count ---" ps -p$TARGET_PID-o nlwp # 打開的文件描述符 echo"" echo"--- Open Files Count ---" ls /proc/$TARGET_PID/fd 2>/dev/null | wc -l # 環(huán)境變量(部分) echo"" echo"--- Key Environment Variables ---" cat /proc/$TARGET_PID/environ 2>/dev/null | tr'?'' '| grep -E"HOME|PATH|JAVA_HOME|NGINX"| head -10 # 內(nèi)存映射 echo"" echo"--- Memory Mappings ---" cat /proc/$TARGET_PID/maps | awk'{print $6}'| sort -u | head -20
6 結(jié)論
top、ps、free是 Linux 運維工程師最常用的三個監(jiān)控命令,每個命令都有其特定的使用場景和優(yōu)勢。top適合實時監(jiān)控和交互式分析,可以持續(xù)觀察系統(tǒng)狀態(tài)的變化;ps適合獲取特定時刻的進程快照,便于腳本化和精確查找;free適合分析內(nèi)存使用狀況。
理解這些命令輸出字段的含義是正確判斷系統(tǒng)狀態(tài)的前提。特別需要注意:top和ps的 CPU 使用率是采樣瞬間的值,不完全等同于 CPU 的平均使用率;free的buff/cache不是"浪費"的內(nèi)存,而是內(nèi)核主動管理的緩存;available是判斷應(yīng)用程序可用內(nèi)存的最準(zhǔn)確指標(biāo),而不是free。
實際排查中,應(yīng)該綜合使用這三個命令,結(jié)合/proc文件系統(tǒng)提供的信息,形成對系統(tǒng)狀態(tài)的完整判斷。養(yǎng)成良好的監(jiān)控和分析習(xí)慣,才能在系統(tǒng)出現(xiàn)問題時快速定位根因。
參考資料:
man top
man ps
man free
/proc/meminfo文檔
man proc(proc 文件系統(tǒng)說明)
-
cpu
+關(guān)注
關(guān)注
68文章
11332瀏覽量
225984 -
Linux
+關(guān)注
關(guān)注
88文章
11822瀏覽量
219600 -
命令
+關(guān)注
關(guān)注
5文章
759瀏覽量
23981
原文標(biāo)題:運維每天都在用的 top、ps、free,到底該怎么看?
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
Linux系統(tǒng)中這三個命令的完整功能和正確查看方法
評論