シェルスクリプトから各コアのCPU負荷を取得します。

シェルスクリプトから各コアのCPU負荷を取得します。

シェルスクリプトでは、コアあたりのCPU負荷をパーセントで報告する必要がありますが、たとえば、mpstatをしばらく実行することはできません。。デフォルトでは、押されたtopときに表示される情報が私が望むものだと思います1が、この情報をバッチモードで表示するように上部を設定することはできません(少なくとも方法はわかりません)。構成を使用してファイルを作成できますが、~/.toprcユーザーがその構成を台無しにしないことを願っています。

出力を表示してmpstat解析しましたが、これは間隔時間として秒のみをサポートします。私のスクリプトはSNMPを介して呼び出され、応答を1秒間待つとタイムアウトが発生するため、これはオプションではありません。

コアあたりのCPU負荷を取得する他の方法はありますか?私はparsingについて読みました/proc/statが、これが最後の手段に近いと思います。

ベストアンサー1

dstat(以下の例)などのユーティリティを使用したり、/ proc / statを直接ポーリング(下の例)など、CPU負荷を1秒未満でポーリングする方法はいくつかあります。

技術的な例に進む前に、2つの長所と短所を検討してみましょう。

dstat を使用するには、クイック crontab( */1 * * * * ) を実行し、結果を確認できる統計ファイルにパイプする必要があります。利点は、SNMPタイムアウトが問題にならないことです。欠点は、実際には即時ではなく、実際にこのデータを探していないときにcrontabを実行すると影響を与える可能性があることです。その影響はわずかかもしれませんが、まだ存在します。

/proc/statを使用するには、/proc/statの内容を2回ポーリングする必要があります。 /proc/statの内容はブートから蓄積されます。したがって、現在の負荷を計算するには、最初のポーリングと2番目のポーリングの結果を減算する必要があります。欠点は、この計算を可能にするには一定の形式の遅延が必要であることです。次の例では、待機時間を1秒未満のレベルに短縮しました。これは必要に応じて行われますが、データサンプルが非常に近いので、精度がどれほど絶対であるかはわかりません。

dstatを使用してください。 /etc/crontabに次の行を追加します。

*/1  *  *  *  *  root    echo $((100-`dstat -c -C0 --noheaders --nocolor 1 1 | grep -v "\-\|u" | awk 'NR == 2' | tr -s " " | cut -d \  -f 4`)) > /tmp/cpuload

1分に1回だけ更新されます。より頻繁に更新するには、2行目を追加し、コマンドの前にスリープ30を追加します。

*/1  *  *  *  *   root    sleep 30; echo $((100-`dstat -c -C0 --noheaders --nocolor 1 1 | grep -v "\-\|u" | awk 'NR == 2' | tr -s " " | cut -d \  -f 4`)) > /tmp/cpuload

cronをさらに使用(乱用)して1秒未満の結果を得ることもできますが、これはまったく異なるトピックです。

説明する:

dstat -c -C 0 --noheaders --nocolor 1 0

-cはCPUデータのみを表示します。

-C は CPU0 を選択します。別のCPUを選択するには、番号を変更してください。

--noheaders --nocolor(-noupdate 暗黙) 表示される内容を単純化します。

1統計の読み取りが1秒遅れます。

1 2番目の統計を読み、終了します。通話後に落ち着く時間をください。

grep -v "-\|u"

データではなく行を削除する

awk 'NR == 2'

2番目の行を選択します。

tr-s""

画面には見えますが、システムの使用には適していない余分なスペースを切り取ります。

切り取り -d\-f 4

-d \(\(エスケープ) スペースの後にスペースが続きます。 -f 4 はアイドルを選択します。

$(())

bash算術演算、100からアイドルシステムを引きます。

/proc/statを使用してください。

cpuload.shとして保存します。

#!/bin/bash

#Calculation delay. Without a delay, there is no way to determine current 
#values. The content or /proc/stat is cumulitative from last boot.  
# in seconds; sleep must be able to support float values
dly=3

function calculate {

#load arrays
IFS=' ' read -r -a firstarr <<< "$1"
IFS=' ' read -r -a secondarr <<< "$2"

#clear name fields in array so that calculations don't get messy
firstarr[0]=0 ;
secondarr[0]=0 ;

#clear values 
firsttotcpu=0
secondtotcpu=0

#calculate the begining interrupt counts
for f in ${firstarr[@]}; 
    do 
        let firsttotcpu+=$f; 
done
firstidle=$((${firstarr[4]}+${firstarr[5]})); 

#calculate the ending interrupt counts
for l in ${secondarr[@]}; 
    do
        let secondtotcpu+=$l; 
    done; 
secondidle=$((${secondarr[4]}+${secondarr[5]})); 

#calculate the relative change counts
insttotcpu=$(( secondtotcpu - firsttotcpu ))
instidle=$(( secondidle - firstidle ))

#calculate the utilization percentage. must be done external to bash as it's a
#floating calculation
cpu_load=$( echo | awk -v tot=$insttotcpu -v idl=$instidle ' { print ( ( ( tot - idl ) / tot ) * 100 ) } ' )

echo -n $cpu_load " " 


} 
export -f calculate

#main execution

oldIFS=$IFS

IFS=$'\n' cpu_start=( $( grep cpu /proc/stat ) );

#must delay to get difference
sleep $dly

IFS=$'\n' cpu_end=( $( grep cpu /proc/stat ) );

cpucount=${#cpu_start[@]}

#uncomment this for loop to enable printing the cpu name above the percentages
#for i in ${cpu_start[@]};
#    do
#        IFS=' ' read -r -a name <<< "$i"
#        echo -n ${name[0]} " "
#done
#echo ""

for (( i=0; i<$cpucount; i++ ))
    do
        calculate "${cpu_start[$i]}" "${cpu_end[$i]}"

done

echo ""

IFS=$oldIFS

おすすめ記事