Calculando a média por uso de núcleo de /proc/stat
A melhor solução que usei até agora é usar bc
para considerar a aritmética de ponto flutuante:
# 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
O uso médio de cpu por núcleo pode ser calculado diretamente de /proc/stat
(Créditos para @mikeserv para a sugestão de usar /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
ou ainda mais curto, fazendo uso extensivo da atribuição direta de matriz do 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
Uma solução baseada em top
Isso também pode ser obtido sem a instalação de uma ferramenta adicional com top
(usei isso em uma versão posterior post .) Por padrão top
mostra apenas o carregamento médio da cpu quando é iniciado, mas mostrará todos os cpus quando você pressione 1
. Para poder usar a saída cpu de top
quando usá-la no modo de saída em lote, precisaremos torná-la o comportamento padrão quando top
for iniciado. Isso pode ser feito usando um arquivo ~/.toprc
. Felizmente, isso pode ser criado automaticamente: inicie top
press 1
e pressione W
, o que gerará o arquivo ~/.toprc
em sua homefolder. Quando você executar top -bn 1 | grep -F '%Cpu'
, verá que top
agora gera todos os seus núcleos. Agora já temos tudo de que precisamos para fazer isso funcionar. Todas as informações que preciso estão na coluna 3
da matriz que será a saída de top
.
Há apenas um problema: quando o uso da CPU para um núcleo atinge 100%
, a matriz que o comando gera moverá a coluna com a carga atual da coluna 3
para a coluna 2
. Assim, com awk '{print $3}'
, você verá us,
como saída para a coluna 3
. Se você está bem com isso, deixe isso. Se não, você pode ter awk
print column 2
também. Será apenas :
. Uma solução que evita todas essas armadilhas é:
top -bn 2 | grep -F '%Cpu' | tail -n 4 | gawk '{print $2 $3}' | tr -s '\n\:\,[:alpha:]' ' '
ele retira a saída de todas as novas linhas de caracteres \n
, ,
e letras [:alpha:]
e remove todos menos um único espaço em branco -s
.