如何使用標準 *nix 工具通過 bash 腳本獲取每個核心的 cpu 使用率
我正在編寫一個 bash 腳本來
dwm
使用xsetroot
. 一切都按預期工作。我目前缺少的是一種簡單的方法,它只使用標準*nix
工具來給我係統上每個核心的目前負載(我有 4 個核心。)。我不知道如何做到這一點,例如使用top
. 到目前為止,我在這個網站上找到的所有其他文章都只處理平均負載。以前有人做過嗎?我希望每個核心都使用它的主要原因是有一個便宜且粗糙的工具來檢查程序是否正在執行我並行編寫的一些程式碼(例如,for each loop)。
計算每個核心的平均使用量
/proc/stat
到目前為止,我提出的最佳解決方案
bc
用於解釋浮點運算:# Calculate average cpu usage per core. # user nice system idle iowait irq softirq steal guest guest_nice # cpu0 30404 2382 6277 554768 6061 0 19 0 0 0 A=($(sed -n '2,5p' /proc/stat)) # user + nice + system + idle B0=$((${A[1]} + ${A[2]} + ${A[3]} + ${A[4]})) B1=$((${A[12]} + ${A[13]} + ${A[14]} + ${A[15]})) B2=$((${A[23]} + ${A[24]} + ${A[25]} + ${A[26]})) B3=$((${A[34]} + ${A[35]} + ${A[36]} + ${A[37]})) sleep 2 # user + nice + system + idle C=($(sed -n '2,5p' /proc/stat)) D0=$((${C[1]} + ${C[2]} + ${C[3]} + ${C[4]})) D1=$((${C[12]} + ${C[13]} + ${C[14]} + ${C[15]})) D2=$((${C[23]} + ${C[24]} + ${C[25]} + ${C[26]})) D3=$((${C[34]} + ${C[35]} + ${C[36]} + ${C[37]})) # cpu usage per core E0=$(echo "scale=1; (100 * ($B0 - $D0 - ${A[4]} + ${C[4]}) / ($B0 - $D0))" | bc) E1=$(echo "scale=1; (100 * ($B1 - $D1 - ${A[15]} + ${C[15]}) / ($B1 - $D1))" | bc) E2=$(echo "scale=1; (100 * ($B2 - $D2 - ${A[26]} + ${C[26]}) / ($B2 - $D2))" | bc) E3=$(echo "scale=1; (100 * ($B3 - $D3 - ${A[37]} + ${C[37]}) / ($B3 - $D3))" | bc) echo $E0 echo $E1 echo $E2 echo $E3
每個核心的平均 cpu 使用率可以直接從
/proc/stat
(致 @mikeserv 以獲取使用提示/proc/stat
)計算:# Here we make use of bash direct array assignment A0=($(sed '2q;d' /proc/stat)) A1=($(sed '3q;d' /proc/stat)) A2=($(sed '4q;d' /proc/stat)) A3=($(sed '5q;d' /proc/stat)) # user + nice + system + idle B0=$((${A0[1]} + ${A0[2]} + ${A0[3]} + ${A0[4]})) B1=$((${A1[1]} + ${A1[2]} + ${A1[3]} + ${A1[4]})) B2=$((${A2[1]} + ${A2[2]} + ${A2[3]} + ${A2[4]})) B3=$((${A3[1]} + ${A3[2]} + ${A3[3]} + ${A3[4]})) sleep 0.2 C0=($(sed '2q;d' /proc/stat)) C1=($(sed '3q;d' /proc/stat)) C2=($(sed '4q;d' /proc/stat)) C3=($(sed '5q;d' /proc/stat)) # user + nice + system + idle D0=$((${C0[1]} + ${C0[2]} + ${C0[3]} + ${C0[4]})) D1=$((${C1[1]} + ${C1[2]} + ${C1[3]} + ${C1[4]})) D2=$((${C2[1]} + ${C2[2]} + ${C2[3]} + ${C2[4]})) D3=$((${C3[1]} + ${C3[2]} + ${C3[3]} + ${C3[4]})) # cpu usage per core E0=$(((100 * (B0 - D0 - ${A0[4]} + ${C0[4]})) / (B0 - D0))) E1=$(((100 * (B1 - D1 - ${A1[4]} + ${C1[4]})) / (B1 - D1))) E2=$(((100 * (B2 - D2 - ${A2[4]} + ${C2[4]})) / (B2 - D2))) E3=$(((100 * (B3 - D3 - ${A3[4]} + ${C3[4]})) / (B3 - D3))) echo $E0 echo $E1 echo $E2 echo $E3
通過廣泛使用 bash 直接數組賦值甚至更短:
# Here we make use of bash direct array assignment by assigning line # 2 to 4 to one array A=($(sed -n '2,5p' /proc/stat)) # user + nice + system + idle B0=$((${A[1]} + ${A[2]} + ${A[3]} + ${A[4]})) B1=$((${A[12]} + ${A[13]} + ${A[14]} + ${A[15]})) B2=$((${A[23]} + ${A[24]} + ${A[25]} + ${A[26]})) B3=$((${A[34]} + ${A[35]} + ${A[36]} + ${A[37]})) sleep 0.2 # user + nice + system + idle C=($(sed -n '2,5p' /proc/stat)) D0=$((${C[1]} + ${C[2]} + ${C[3]} + ${C[4]})) D1=$((${C[12]} + ${C[13]} + ${C[14]} + ${C[15]})) D2=$((${C[23]} + ${C[24]} + ${C[25]} + ${C[26]})) D3=$((${C[34]} + ${C[35]} + ${C[36]} + ${C[37]})) # cpu usage per core E0=$((100 * (B0 - D0 - ${A[4]} + ${C[4]}) / (B0 - D0))) E1=$((100 * (B1 - D1 - ${A[15]} + ${C[15]}) / (B1 - D1))) E2=$((100 * (B2 - D2 - ${A[26]} + ${C[26]}) / (B2 - D2))) E3=$((100 * (B3 - D3 - ${A[37]} + ${C[37]}) / (B3 - D3))) echo $E0 echo $E1 echo $E2 echo $E3
有
top
基礎的解決方案這也可以在不安裝額外工具的情況下實現
top
(我在後面的文章中使用了這個。)預設情況下top
,它只顯示啟動時的平均 cpu 負載,但當你按下時它會顯示所有 cpu1
。為了能夠top
在批量輸出模式下使用它的 cpu 輸出,我們需要將其設為top
啟動時的預設行為。這可以通過使用~/.toprc
文件來完成。幸運的是,這可以自動創建:開始top
按下1
並按下W
將~/.toprc
在您的主文件夾中生成文件。當你現在執行時top -bn 1 | grep -F '%Cpu'
,你會看到top
現在輸出你所有的核心。現在我們已經擁有了完成這項工作所需的一切。我需要的所有資訊都在3
數組的列中,它將成為top
.只有一個問題:當核心的 cpu 使用率達到
100%
命令輸出的數組時,會將目前負載的列從 column 移動3
到 column2
。因此,awk '{print $3}'
您將看到us,
column 的輸出3
。如果你沒問題,就離開吧。如果不是,您也可以有awk
列印列2
。它只是:
。避免所有這些陷阱的解決方案是:top -bn 2 | grep -F '%Cpu' | tail -n 4 | gawk '{print $2 $3}' | tr -s '\n\:\,[:alpha:]' ' '
它去除所有換行符和字母的輸出
\n
,並刪除除一個空格之外的所有內容。,``[:alpha:]``-s
這將創建一個 bash 數組,其元素是每個 CPU 的負載:
loads=($(mpstat -P ALL 1 1 | awk '/Average:/ && $2 ~ /[0-9]/ {print $3}'))
由於 bash 數組從零開始編號,因此第二個 CPU 的負載將列印為:
echo ${loads[1]}
這需要實用程序
mpstat
。要將其安裝在類似 debian 的系統上,請執行:apt-get install sysstat
這個怎麼運作
產生的有點冗長的輸出
mpstat
看起來像:$ mpstat -P ALL 1 1 Linux 3.2.0-4-amd64 (MyMachine) 08/30/2014 _x86_64_ (2 CPU) 10:12:35 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle 10:12:36 PM all 1.49 0.00 1.49 0.00 0.00 0.00 0.00 0.00 97.01 10:12:36 PM 0 0.00 0.00 2.02 0.00 0.00 0.00 0.00 0.00 97.98 10:12:36 PM 1 1.96 0.00 1.96 0.00 0.00 0.00 0.00 0.00 96.08 Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle Average: all 1.49 0.00 1.49 0.00 0.00 0.00 0.00 0.00 97.01 Average: 0 0.00 0.00 2.02 0.00 0.00 0.00 0.00 0.00 97.98 Average: 1 1.96 0.00 1.96 0.00 0.00 0.00 0.00 0.00 96.08
where
-P ALL
告訴mpstat
顯示所有 cpus,參數1 1
告訴它每秒列印輸出並在第一秒後停止。要僅選擇我們想要的值,請
awk
使用以下命令:awk '/Average:/ && $2 ~ /[0-9]/ {print $3}'
這僅選擇最後一行(以開頭的行
Average:
,其中僅選擇第二列為數字的行。對於這些行,將列印第三列(cpu load)。由於使用了括號,
mpstat
-awk
管道的輸出被擷取到一個 bash 數組中。