Repete um comando a cada x intervalo de tempo no terminal?

124

Como posso repetir um comando a cada intervalo de tempo, para que ele possa executar comandos para os diretórios checking ou monitoring ?

Não há necessidade de um script, eu preciso apenas de um simples comando para ser executado no terminal.

    
por muru 06.03.2014 / 16:52

8 respostas

192

Você pode usar o comando watch , o watch é usado para executar qualquer comando designado em intervalos regulares.

Abra o Terminal e digite:

watch -n x <your command>

altere x para o tempo em segundos que você deseja.

Para obter mais ajuda sobre como usar o comando watch e suas opções, execute man watch ou visite este link .

Por exemplo: o seguinte lista, cada 60s , no mesmo Terminal, o conteúdo do diretório Desktop para que você possa saber se alguma alteração ocorreu:

watch -n 60 ls -l ~/Desktop
    
por nux 06.03.2014 / 16:54
77

Você também pode usar este comando no terminal, além da resposta do nux:

while true; do <your_command>; sleep <interval_in_seconds>; done

Exemplo

while true; do ls; sleep 2; done

Este comando imprimirá a saída de ls em um intervalo de 2 segundos.

Use Ctrl + C para parar o processo.

Existem algumas desvantagens de watch

  • Não é possível usar comandos com alias.
  • Se a saída de qualquer comando for muito longa, a rolagem não funcionará corretamente.
  • Há alguns problemas para definir intervalo máximo de tempo além de determinado valor.
  • watch interpretará sequências de cores ANSI passando caracteres de escape usando a opção -c ou --color . Por exemplo, a saída de pygmentize funcionará, mas falhará em ls --color=auto .

Nas circunstâncias acima, isso pode parecer uma opção melhor.

    
por souravc 06.03.2014 / 17:00
34

Só queria falar com as respostas souravc e nux :

  1. Embora watch funcione perfeitamente no Ubuntu, você pode evitar isso se quiser que seu "Unix-fu" seja puro - no FreeBSD, por exemplo, watch é um comando para "bisbilhotar outra linha tty".
  2. while true; do command; sleep SECONDS; done também tem uma ressalva - seu comando pode ser mais difícil de matar usando CTR + C . Você pode querer preferir while sleep SECONDS; do command; done - não é apenas mais curto, mas também mais fácil de interromper. A ressalva é que ele primeiro irá dormir e, em seguida, executará o seu comando, então você precisará aguardar alguns SECONDS antes que a primeira ocorrência do comando aconteça.
por d33tah 08.03.2014 / 16:51
11

Soa como a tarefa ideal para o daemon cron , que permite executar comandos periódicos. Execute o comando crontab -e para começar a editar a configuração do cron do seu usuário. Seu formato está documentado em crontab (5) . Basicamente, você tem cinco campos separados por espaço e relacionados ao tempo seguidos por um comando:

The time and date fields are:

       field          allowed values
       -----          --------------
       minute         0-59
       hour           0-23
       day of month   1-31
       month          1-12 (or names, see below)
       day of week    0-7 (0 or 7 is Sunday, or use names)

Por exemplo, se você gostaria de executar um script Python em todas as terças-feiras, 11:00:

0 11 * * 1 python ~/yourscript.py

Existem também alguns nomes especiais que substituem a hora, como @reboot . Muito útil se você precisar criar um diretório temporário. Do meu crontab (listado com crontab -l ):

# Creates a temporary directory for ~/.distcc at boot
@reboot ln -sfn "$(mktemp -d "/tmp/distcc.XXXXXXXX")" "$HOME/.distcc"
    
por Lekensteyn 07.03.2014 / 19:54
5

Se você estiver monitorando o sistema de arquivos, então inotifywait é brilhante e certamente adiciona menos carga ao seu sistema.

Exemplo:

No terminal primeiro , digite este comando:

$ inotifywait .

Então, no terminal 2nd , qualquer comando que afete o diretório atual,

$ touch newfile

Em seguida, no terminal original, inotifywait irá acordar e reportar o evento

./ CREATE newfile2

Ou em um loop

$ while true ; do inotifywait . ; done
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ DELETE newfile
Setting up watches.  
Watches established.
./ CREATE,ISDIR newdir
Setting up watches.  
Watches established.
    
por X Tian 06.03.2014 / 17:35
4

Você pode criar seu próprio comando repeat executando as seguintes etapas; créditos aqui :

Primeiro, abra seu arquivo .bash_aliases :

$ xdg-open ~/.bash-aliases

Em segundo lugar, cole essas linhas na parte inferior do arquivo e salve:

repeat() {
n=$1
shift
while [ $(( n -= 1 )) -ge 0 ]
do
    "$@"
done
}

Em terceiro lugar, feche e abra novamente o seu terminal ou digite:

$ source ~/.bash_aliases

Et voilà! Agora você pode usá-lo assim:

$ repeat 5 echo Hello World !!!

ou

$ repeat 5 ./myscript.sh
    
por Blufter 08.08.2014 / 21:38
4

você pode usar o crontab. execute o comando crontab -e e abra-o com seu editor de texto preferido e, em seguida, adicione esta linha

*/10 * * * *  /path-to-your-command

Isso executará seu comando a cada 10 minutos

* */4 * * *  /path-to-your-command

Isso executará seu comando a cada 4 horas

Outra solução possível

$ ..some command...; for i in $(seq X); do $cmd; sleep Y; done

X número de vezes para repetir.

Y tempo para esperar para repetir.

Exemplo:

$ echo; for i in $(seq 5); do $cmd "This is echo number: $i"; sleep 1;done
    
por Maythux 07.03.2014 / 06:57
2

Outra preocupação com a abordagem "watch" proposta acima é que ela exibe o resultado apenas quando o processo é concluído. "date; sleep 58; date" exibirá as 2 datas somente após 59 segundos ... Se você iniciar algo em execução por 4 minutos, que exiba lentamente várias páginas de conteúdo, você realmente não o verá.

Por outro lado, a preocupação com a abordagem "while" é que ela não leva em consideração a duração da tarefa.

while true; do script_that_take_between_10s_to_50s.sh; sleep 50; done

Com isso, o script será executado a cada minuto, em algum momento pode levar 1m40. Portanto, mesmo que um cron possa executá-lo a cada minuto, aqui não será.

Então, para ver a saída no shell conforme ela é gerada e esperar pelo tempo exato de solicitação, você precisa olhar o tempo antes e depois e fazer o loop com o tempo.

Algo como:

while ( true ); do
  echo Date starting 'date'
  before='date +%s'
  sleep 'echo $(( ( RANDOM % 30 )  + 1 ))'
  echo Before waiting 'date'
  after='date +%s'
  DELAY='echo "60-($after-$before)" | bc'
  sleep $DELAY
  echo Done waiting 'date'
done

Isso produzirá isso:

Como você pode ver, o comando é executado a cada minuto:

Date starting Mon Dec 14 15:49:34 EST 2015
Before waiting Mon Dec 14 15:49:52 EST 2015
Done waiting Mon Dec 14 15:50:34 EST 2015

Date starting Mon Dec 14 15:50:34 EST 2015
Before waiting Mon Dec 14 15:50:39 EST 2015
Done waiting Mon Dec 14 15:51:34 EST 2015

Então apenas substitua o comando "sleep echo $(( ( RANDOM % 30 ) + 1 )) " pelo que você quiser e que será executado, no terminal / shell, exatamente a cada minuto. Se você quiser outro horário, basta alterar os "60" segundos com o que precisar.

Versão mais curta sem as linhas de depuração:

while ( true ); do
  before='date +%s'
  sleep 'echo $(( ( RANDOM % 30 )  + 1 ))' # Place you command here
  after='date +%s'
  DELAY='echo "60-($after-$before)" | bc'
  sleep $DELAY
done
    
por jmspaggi 14.12.2015 / 21:56