Existem várias maneiras de realizar polling sub-sccond do carregamento de cpu, usando um utilitário, como dstat (exemplo abaixo) ou por polling direto / proc / stat (exemplo também abaixo).
Vamos analisar os prós e contras de ambos antes de passarmos aos exemplos técnicos.
Para usar o dstat, você precisará executar um crontab rápido (* / 1 * * * *) e canalizar o resultado para um arquivo de estatísticas que possa ser verificado. A vantagem é que seus tempos limite de SNMP não serão um problema, a desvantagem, não é realmente instantânea, e a execução do crontab quando você não está realmente procurando esses dados tem um impacto. O impacto pode ser insignificante, mas ainda assim está lá.
Para usar / proc / stat, você deve pesquisar o conteúdo de / proc / stat duas vezes. O conteúdo de / proc / stat é cumulativo desde a inicialização. Portanto, os resultados da primeira sondagem e da segunda sondagem precisam ser subtraídos uns dos outros e, em seguida, o cálculo da carga atual pode ser feito. A desvantagem é que deve haver alguma forma de atraso para fazer esse cálculo. No exemplo abaixo, o atraso caiu para menos de um segundo. Isso atenderia às suas necessidades, mas as amostras de dados são tão próximas que não sei ao certo como a precisão é absoluta.
Usando dstat;
Adicione esta linha ao / 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
Isso só é atualizado uma vez a cada minuto. Se você quiser atualizações mais frequentes, adicione uma segunda linha e prefira o comando com sleep 30, como
*/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
É possível usar o cronômetro (abuso) ainda mais longe e chegar a resultados secundários, mas esse é outro assunto totalmente diferente.
explicação:
dstat -c -C 0 --noheaders --nocolor 1 0
-c mostra apenas dados da cpu
-C selecione cpu0. mude a numeração para selecionar outra cpu
- noheaders --nocolor (implied --noupdate) simplifica o que vemos
1 atraso de um segundo na leitura de estatísticas
1 saída após segunda leitura das estatísticas. Dando tempo para se estabelecer após a invocação.
grep -v "-\|u"
remover linhas de dados não
awk 'NR == 2'
selecione a segunda linha.
tr -s " "
reduza os espaços extras que parecem bonitos na tela, mas não para uso do sistema
cut -d \ -f 4
-d \ (há um espaço após a linha delineada do espaço \ (escape)
-f 4 selecione a inatividade. sim, é visualmente 3, mas o espaço no início da linha conta como um campo, eliminando a contagem de campo.
$ (( ))
operações aritméticas bash, subtraindo o sistema ocioso de 100.
Usando / proc / stat;
Salvar como 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