Bash

如何使用標準 *nix 工具通過 bash 腳本獲取每個核心的 cpu 使用率

  • January 31, 2022

我正在編寫一個 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 負載,但當你按下時它會顯示所有 cpu 1。為了能夠top在批量輸出模式下使用它的 cpu 輸出,我們需要將其設為top啟動時的預設行為。這可以通過使用~/.toprc文件來完成。幸運的是,這可以自動創建:開始top按下1並按下W~/.toprc在您的主文件夾中生成文件。當你現在執行時top -bn 1 | grep -F '%Cpu',你會看到top現在輸出你所有的核心。現在我們已經擁有了完成這項工作所需的一切。我需要的所有資訊都在3數組的列中,它將成為top.

只有一個問題:當核心的 cpu 使用率達到100%命令輸出的數組時,會將目前負載的列從 column 移動3到 column 2。因此,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 數組中。

引用自:https://unix.stackexchange.com/questions/152988