Bash

用於評估 CPU 使用率的 Bash 腳本

  • August 22, 2019

我正在嘗試編寫一個 BASH 腳本,它將評估並在終端中顯示所有核心及其目前負載的列表。我正在使用/proc/stat. 例如:

cat /proc/stat
    user nice system idle iowait  irq  softirq steal guest guest_nice
cpu  4705 356  584    3699   23    23     0       0     0          0

user並通過對、nicesystem、求和來評估使用的 CPU 時間,並通過對irqsoftirq求和來評估stealCPU 空閒時間。然後我將使用的 CPU 時間 + CPU 空閒時間相加以獲得總 CPU 時間並將 CPU 使用時間除以總 CPU 時間。idle``iowait

這種方法的問題在於,這是自系統上次啟動以來的平均 CPU 使用率。為了獲得目前使用情況,我需要檢查兩次/proc/stat並使用兩次檢查之間的總 CPU 時間和已用 CPU 時間之間的差異,然後將結果除以它們之間的時間差異(以秒為單位)。為此,我使用了一個while無限循環和一個 sleep 命令。我希望輸出格式如下:

CPU: 10%
CPU0: 15%
CPU1: 5%
CPU2: 7%
CPU3: 13%

我希望所有核心的總 CPU 使用率和每個核心的 CPU 使用率在每次睡眠後自動更新。到目前為止,這是我的程式碼:

#!/bin/bash

PREV_CPU_USE=0
PREV_CPU_IDLE=0
PREV_EPOCH_TIME=0

# Setting the delimiter
IFS=$'\n'

while true; do
 # Getting the total CPU usage
 CPU_USAGE=$(head -n 1 /proc/stat)

 # Getting the Linux Epoch time in seconds
 EPOCH_TIME=$(date +%s)

 # Splitting the /proc/stat output
 IFS=" " read -ra USAGE_ARRAY <<< "$CPU_USAGE"

 # Calculating the used CPU time, CPU idle time and CPU total time
 CPU_USE=$((USAGE_ARRAY[1] + USAGE_ARRAY[2] + USAGE_ARRAY[3] + USAGE_ARRAY[6] + USAGE_ARRAY[7] + USAGE_ARRAY[8] ))
 CPU_IDLE=$((USAGE_ARRAY[4] + USAGE_ARRAY[5]))

 # Calculating the differences
 DIFF_USE=$((CPU_USE - PREV_CPU_USE))
 DIFF_IDLE=$((CPU_IDLE - PREV_CPU_IDLE))
 DIFF_TOTAL=$((DIFF_USE + DIFF_IDLE))
 DIFF_TIME=$((EPOCH_TIME - PREV_EPOCH_TIME))

 #Printing the line and ommiting the trailing new line and using carrier trailer to go to the beginning of the line
 echo -en "${USAGE_ARRAY[0]} Usage: $((DIFF_USE*100/(DIFF_TOTAL*DIFF_TIME)))%                          \\r\\n"
 echo -en "${USAGE_ARRAY[0]} Idle: $((DIFF_IDLE*100/(DIFF_TOTAL*DIFF_TIME)))%                         \\r"

 # Assigning the old values to the PREV_* values
 PREV_CPU_USE=$CPU_USE
 PREV_CPU_IDLE=$CPU_IDLE
 PREV_EPOCH_TIME=$EPOCH_TIME

 # Sleep for one second 
 sleep 1
done

在這裡,我簡化了腳本,實際上我只在兩條不同的行上列印了目前的 CPU 使用率和空閒 CPU 時間,但即使cpu Idle保留在一行上,cpu Usage也會添加新的行,例如:

cpu Usage: 0%                         
cpu Usage: 0%                         
cpu Usage: 0%                         
cpu Idle: 99%

是否可以選擇cpu Usage僅在腳本的整個持續時間內使用一行?

我認為您希望cpu Usage每次都在同一行上顯示字元串並cpu Idle立即緊跟該行。要實現這一點,您可以使用tputel( clr_eol) 終端功能來刪除行和cuu( parm_up_cursor) 將 n 行向上移動。您可以在 中閱讀有關終端功能的資訊man terminfo。您的腳本將如下所示:

#!/bin/bash

PREV_CPU_USE=0
PREV_CPU_IDLE=0
PREV_EPOCH_TIME=0

# Setting the delimiter
IFS=$'\n'
counter=0

while true; do
 # Getting the total CPU usage
 CPU_USAGE=$(head -n 1 /proc/stat)

 # Getting the Linux Epoch time in seconds
 EPOCH_TIME=$(date +%s)

 # Splitting the /proc/stat output
 IFS=" " read -ra USAGE_ARRAY <<< "$CPU_USAGE"

 # Calculating the used CPU time, CPU idle time and CPU total time
 CPU_USE=$((USAGE_ARRAY[1] + USAGE_ARRAY[2] + USAGE_ARRAY[3] + USAGE_ARRAY[6] + USAGE_ARRAY[7] + USAGE_ARRAY[8] ))
 CPU_IDLE=$((USAGE_ARRAY[4] + USAGE_ARRAY[5]))

 # Calculating the differences
 DIFF_USE=$((CPU_USE - PREV_CPU_USE))
 DIFF_IDLE=$((CPU_IDLE - PREV_CPU_IDLE))
 DIFF_TOTAL=$((DIFF_USE + DIFF_IDLE))
 DIFF_TIME=$((EPOCH_TIME - PREV_EPOCH_TIME))

 printf "\r%s%s Usage: %d (counter = %d)\n" "$(tput el)" "${USAGE_ARRAY[0]}" "$((DIFF_USE*100/(DIFF_TOTAL*DIFF_TIME)))" "$counter"
 printf "\r%s%s Idle: %d (counter = %d)" "$(tput el)" "${USAGE_ARRAY[0]}" "$((DIFF_IDLE*100/(DIFF_TOTAL*DIFF_TIME)))" "$counter"
 counter=$((counter + 1))

 tput cuu 1

 # Assigning the old values to the PREV_* values
 PREV_CPU_USE=$CPU_USE
 PREV_CPU_IDLE=$CPU_IDLE
 PREV_EPOCH_TIME=$EPOCH_TIME

 # Sleep for one second 
 sleep 1
done

我為調試目的添加了一個額外的counter變數。它在每次列印後遞增,以通知使用者舊行被螢幕上的新行替換。

我還替換了你的電話echoprintf因為它更便攜。

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