Começando com o comando sar 1 1
:
# sar 1 1
Linux 4.14.14 (sys.local) 02/08/2018 _x86_64_ (4 CPU)
09:38:01 PM CPU %user %nice %system %iowait %steal %idle
09:38:02 PM all 5.74 0.00 1.50 0.00 0.00 92.77
Average: all 5.74 0.00 1.50 0.00 0.00 92.77
Queremos a coluna% iowait. Uma string comum para corresponder a regex em cada linha é all
em CPU
, portanto:
# sar 1 1 | awk '/all|iowait/{print $7}'
%iowait
0.00
0.00
Nesse caso, adicionamos iowait
à regex para confirmar que obtivemos a coluna correta, $7
. (Veja man awk
para mais detalhes sobre o uso do awk.) Nosso próximo passo é salvar esses valores para uso em nosso script:
# iowait=( $( sar 1 1 | awk '/all/{print $7}' ) )
Esta sintaxe var=()
é para uma matriz. Veja man bash
para detalhes. Podemos referenciar esses valores com $ {iowait [1]}, então agora estamos preparados para um loop sobre os dois valores:
# iowait=( $( sar 1 1 | awk '/all/{print $7}' ) ) ; for I in ${iowait[*]} ; do \
echo $I ; \
done
0.25
0.00
Ótimo, quase lá, não podemos comparar esses valores com um condicional. Isso levará algum esforço extra, porque o bash prefere comparar inteiros em vez de floats. Poderíamos multiplicar por 100 antes da comparação, mas é mais fácil usar um atalho bash para descartar os decimais antes da comparação. Para obter 12 de 12,34 na variável $I
, usaremos a sintaxe $ {I %%. *}. Isso remove o sufixo correspondente da variável I
e o regex .*
corresponde a qualquer coisa, portanto, tudo após o decimal. -lt
no bash funcionará dentro de um condicional: if [ ]; then something; fi
Tudo isso é descrito em detalhes em man bash
para referência.
# iowait=( $( sar 1 1 | awk '/all/{print $7}' ) ) ; \
for I in ${iowait[*]} ; do \
if [ ${I%%.*} -lt 2 ] ; then \
echo "$I < 2" ; \
fi ; \
done
0.00 < 2
0.00 < 2
Uma adição final antes de enviarmos nosso e-mail, vamos adicionar um registro de data e hora específico e ver o que está sendo executado durante esse IO alto:
# iowait=( $( sar 1 1 | awk '/all/{print $7}' ) ) ; \
for I in ${iowait[*]} ; do \
if [ ${I%%.*} -lt 2 ] ; then \
echo "$(date -Is): iowait = $I\n $(ps)" ; \
fi ; \
done
2018-02-08T22:09:21-05:00: iowait = 0.25
PID TTY TIME CMD
3431 pts/1 00:00:00 zsh
28148 pts/1 00:00:00 ps
2018-02-08T22:09:21-05:00: iowait = 0.00
PID TTY TIME CMD
3431 pts/1 00:00:00 zsh
28150 pts/1 00:00:00 ps
É claro que melhores opções de ps, como ps eaf
ou ps auxfw
, podem ser usadas como você preferir para mais detalhes. Não, para atingir efetivamente a tarefa (comparando -gt 50
) e enviar o email direcionando nossa saída para mailx
:
# iowait=( $( sar 1 1 | awk '/all/{print $7}' ) ) ; \
for I in ${iowait[*]} ; do \
if [ ${I%%.*} -gt 50 ] ; then echo "$(date -Is): iowait = $I\n $(ps)" |
mailx -s "hi iowait" root ; \
fi ; \
done
Espero que isso responda à sua pergunta e demonstre como alguém pode construir o que deseja, quebrando o problema passo a passo, aproveitando a filosofia unix, muitas ferramentas e páginas de manual.