Este artigo explica como repetir um comando a cada X segundos no Linux, de duas maneiras: usando watch
e usando sleep
em um loop de execução while
(com uma maneira de evitar flutuação de tempo ao usar comandos em loop longos).
watch
para executar um comando a cada X segundoswatch
pode executar um comando repetidamente, exibindo sua saída e erros (a primeira tela cheia). Isso permite que você observe a mudança de saída do programa ao longo do tempo.
Usando watch
para executar um comando a cada X
segundos:
watch -n
Onde:
-n
especifica o intervalo de tempoX
é o intervalo no qual executar o comando, em segundos (com 0,1 segundos sendo o menor valor possível)comando
é o comando que você deseja executarSe o comando contiver barras verticais, aspas ou outros caracteres especiais, use aspas simples, por exemplo: 'comando'
.
Exemplo. O seguinte comando executa ps aux | grep firefox
a cada 5 segundos:
watch -n 5 'ps aux | grep firefox'
O comando watch
tem algumas opções, como destacar as diferenças entre atualizações sucessivas (--differences
/-d
), beep se um comando tem uma saída diferente de zero (--beep
/-b
), e muito mais. Verifique sua página man para obter mais informações.
Você também pode gostar de: Como encontrar arquivos modificados nos últimos N dias ou minutos usando find
sleep
em um loop while
para repetir um comando a cada X segundosOutra maneira de repetir um comando a cada X segundos no Linux é usar um loop while
com o comando sleep
:
while true; do
Aqui, você precisa substituir comando
com o comando a ser executado e X
com o intervalo de tempo em segundos (o número não precisa ser um inteiro, mas não pode ser negativo; você também pode especificar minutos - 1m por exemplo, horas - 1h por exemplo, etc. .).
Exemplo. O seguinte one-liner executa o comando echo $(date)
a cada 5 segundos:
while true; do echo $(date); sleep 5; done
Se você estiver fazendo algo mais complicado, certifique-se de que o intervalo seja menor do que o tempo necessário para o comando terminar, ou então isso pode interferir em algo em seu script.
Também é importante notar que usando isso, o tempo irá variar, dependendo de quanto tempo o comando que você está executando leva para ser concluído. Por exemplo, se você deseja executar um comando a cada 5 segundos, mas esse comando leva 3 segundos para ser concluído, isso fará com que o comando seja executado a cada 8 segundos, em vez de a cada 5 segundos.
Uma solução para evitar essa flutuação de tempo e executar o comando a cada X segundos, independentemente de quanto tempo leva para ser concluído (desde que o comando não leve mais para ser concluído do que o tempo de suspensão), é usar o seguinte:
while true; do
Aqui, substitua comando
pelo comando que deseja executar e ambas as instâncias de X
com o número de segundos após o qual o comando deve ser repetido.
Atenção: Esta solução não é perfeita. Leia a explicação e a alternativa para isso nas edições marcadas mais adiante neste artigo.
Exemplo. O seguinte one-liner repete o comando sleep 3
(não poderia pensar em um exemplo melhor agora de um comando que leva alguns segundos para ser concluído e não é destrutivo de forma alguma caso o usuário não o interrompa - Estou digitando às 5h) a cada 5 segundos:
while true; do sleep 3; sleep $((5 - $(date +%s) % 5)); done
Usando isso, embora o comando (sleep 3
neste caso, pode ser qualquer comando que você deseja) leve 3 segundos para ser concluído, o intervalo entre as execuções é de 5 segundos.
Para testar isso, você pode adicionar um echo $(date)
no início, como este:
while true; do echo $(date); sleep 3; sleep $((5 - $(date +%s) % 5)); done
Você perceberá que a data impressa no terminal está em incrementos de 5 segundos, como este:
Thu 10 Dec 05:48:00 2020
Thu 10 Dec 05:48:05 2020
Thu 10 Dec 05:48:10 2020
Thu 10 Dec 05:48:15 2020
Atenção: Esta solução não é perfeita. Entre a primeira e a segunda execução, o intervalo de tempo pode ser menor do que o especificado. No entanto, as execuções subsequentes usam o intervalo de tempo correto. Se você conhece a melhor maneira de fazer isso, deixe um comentário abaixo.
Dica: Uma solução (via stackexchange) que evita flutuação no tempo e não tem o problema que mencionei acima (portanto, nenhum intervalo de tempo diferente entre a primeira e a segunda execução), mas que não faz uso do comando sleep
, é o seguinte comando de uma linha:**
while true; do currentTime=$(date +%s); elapsedTime=$((currentTime - lastTime)); if [ $elapsedTime -ge
Substitua X
com o intervalo de tempo entre as execuções (em segundos) e comando
com o comando que deseja repetir a cada X segundos.
Uma pequena explicação é necessária aqui. Este loop while
armazena o tempo Unix atual como currentTime
e, em seguida, subtrai o último tempo (lastTime
) do tempo atual, armazenando como elapsedTime
. Em seguida, ele verifica se o tempo decorrido é maior ou igual a X
e se for, ele executa command
(então o comando é repetido a cada X
segundos). E, finalmente, ele define o último tempo para ser igual ao tempo atual, portanto, da próxima vez que for executado, ele pode subtrair lastTime
do currentTime
, o que dá o valor elapsedTime
. Espero que isso faça sentido para você como faz na minha cabeça 😁️.
Exemplo. A seguinte linha repete os comandos echo $(date)
e sleep 2
(usei sleep 2
, portanto, o comando leva alguns segundos para ser verificado, se não for concluído).
while true; do currentTime=$(date +%s); elapsedTime=$((currentTime - lastTime)); if [ $elapsedTime -ge 5 ]; then echo $(date); sleep 2; lastTime=$currentTime; i=0; fi; done
Você também pode gostar de: Como excluir arquivos mais antigos ou mais recentes do que N dias usando find (com exemplos extras)
Esse post foi traduzido do site LinuxUprising.com pela rtland.team.
Confira a versão original desse post em inglês:
How To Repeat A Command Every X Seconds On Linux