Em uma máquina Linux tenho uma série de comandos que oferecem valores numéricos do estado de diferentes sensores.
A chamada desses comandos é algo semelhante ao seguinte:
$ command1
5647
$ command2
76
$ command3
8754
Esses valores mudam em tempo real, e toda vez que quero verificar o status de um deles, tenho que reiniciar o comando... Isso não me faz bem, pois preciso das duas mãos para manipular o hardware.
Meu objetivo é fazer um Bash Script simples que chame esses comandos e mantenha o valor atualizado (em tempo real de forma assíncrona ou atualizando o valor a cada x segundos) assim:
$ ./myScript.sh
command1: x
command2: y
command3: z
command4: v
Onde x
, y
, z
e v
são os valores variáveis.
Bash permite isso de forma simples e eficiente? ou devo optar por fazê-lo em outra linguagem, como Python?
ATUALIZAÇÃO com mais informações:
Meu script atual é:
#!/bin/bash
echo "Célula calibrada: " $(npe ?AI1)
echo "Anemómetro: " $(npe ?AI2)
echo "Célula temperatura: " $(npe ?AI3)
echo "Célula temperatura: " $(npe ?AI4)
npe
sendo um comando de exemplo que retorna o valor numérico. Espero uma saída como esta:
Essa saída eu recebo com o comando watch -n x ./myScript.sh
, onde x
é o valor de atualização de segundos. Se eu editar meu script assim:
#!/bin/bash
while sleep 1; do
clear; # added to keep the information in the same line
echo "Célula calibrada: " $(npe ?AI1);
echo "Anemómetro: " $(npe ?AI2);
echo "Célula temperatura: " $(npe ?AI3);
echo "Célula temperatura: " $(npe ?AI4);
done
Eu recebo minha saída com uma cintilação irritante:
Você pode usar
tput cup 0 0
para enviar o cursor para o canto superior esquerdo da tela.clear
uma vez.Pode ser complicado implementar uma solução em tempo real no bash.
Há muitas maneiras de executar o script uma vez em X segundos que você pode usar
watch
. Imagino que você já tenhamyScript.sh
disponível. Substitua X pelo número de segundos que você precisa.watch -n X ./myScript.sh
while sleep X; do ./myScript.sh; done
atualizado para emular o relógio, você pode limpar a tela entre as iterações. dentro do script ficará assim:
adicione uma das opções acima ao próprio script.
Estou assumindo que a cintilação é porque seus comandos demoram um momento para retornar seus valores. Esta é a minha solução habitual:
A ideia é limparmos a tela no último momento possível.
Se você
clear
imediatamente após osleep
, em vez de imediatamente antes, poderá ler a saída com mais facilidade:No entanto, eu removeria o loop aqui e usaria
watch
para executar o script repetidamente. Essa é uma composição mais flexível de ferramentas individuais.Você pode fazer isso exatamente no bash. Se o texto ainda estiver piscando, você não leu as respostas anteriores completamente.
Você precisa ir para
clear
a tela antes de ecoar os novos valores, não depois.você pode colocar todos os seus comandos dentro do loop while com algum tempo de sono. No exemplo abaixo, coloco sleep a cada 2 segundos. Portanto, o comando date será executado a cada 2 segundos
Você está: exibindo uma linha e executando o comando para exibir a próxima.
Você precisa: executar todos os comandos (sem tocar na tela) e salvar os resultados em 4 vars, depois limpar e exibir esses 4 resultados de uma só vez.
Se eu modificar seu próprio script, tente:
Aqui, a longa execução das 4 solicitações ocorre sem alterar a exibição, então a exibição é atualizada muito rapidamente e exibida de uma só vez com os 4 novos valores.
Isso faz 50 linhas sem piscar, porque usa tput para atualizar cada linha separadamente. Eu coloquei um sono 0,01 entre cada linha para provar isso.
A execução do script com arg y mostra exemplos do que sua janela de terminal usa para posicionar o cursor. Eu codifiquei minhas fugas no eco. O seu pode ser diferente. Para portabilidade, você deve usar tput para gerar as sequências dinamicamente. Para desempenho, você deve obter todas as sequências de tput que precisará para seu aplicativo antecipadamente e armazená-las no shell. Além disso, uma vez que você tenha o texto fixo no lugar uma vez, apenas altere as partes variáveis.
Observe que as posições da tela começam em (0, 0) em tput args. Além disso, os zeros à esquerda nos comandos de tela são interpretados como octais, e é por isso que reformato o número da linha visível com printf. Também é educado mover o cursor para fora do caminho (como (0,0)) após a atualização.
Você pode configurar um loop no bash -- a construção é
while true; do ....; done
onde....
estão seus comandos. Você precisaria Ctrl+ Cpara pará-lo.Você precisa colocar um sono no loop, ou ele simplesmente gritará e consumirá todo o seu tempo de CPU. Os segundos para dormir são um compromisso entre obter os números atuais e ter muita saída.
Se você formatar a saída na largura da tela em colunas fixas (use o comando printf), será mais fácil ver as variações.
Eu provavelmente enviaria a saída de tudo isso para um arquivo (redirecionamento após o "feito"), para que você possa examiná-lo à vontade depois, talvez até grafá-lo ou fazer estatísticas. Você pode executar um
tail -f
comando em outra janela, que mostrará os dados mais recentes sendo adicionados ao arquivo para que você possa vê-los também.Você também pode colocar um
date
comando no loop para marcar cada linha, caso os intervalos entre os dados sejam importantes.Poste novamente se algum deles precisar de mais carne nos ossos.
Após a expiração do sono, ecoe um backspace e reexiba um valor. Isso pressupõe que você esteja em um terminal que pode exibir códigos de escape, a largura e as linhas do terminal, mas funciona como um tiro rápido. Exemplo: Exibir Spinner enquanto aguarda a conclusão de algum processo