Ripete un comando ogni x intervallo di tempo nel terminale?

120

Come posso ripetere un comando ogni intervallo di tempo, in modo che mi consenta di eseguire comandi per controllo o monitoraggio directory?

Non c'è bisogno di uno script, ho bisogno solo di un semplice comando per essere eseguito nel terminale.

    
posta muru 06.03.2014 - 16:52

8 risposte

185

Puoi utilizzare il comando watch , watch è usato per eseguire qualsiasi comando designato a intervalli regolari.

Apri il Terminale e digita:

watch -n x <your command>

cambia x in secondi in secondi.

Per ulteriori informazioni sull'utilizzo del comando watch e le sue opzioni, esegui man watch o visita questo collegamento .

Ad esempio: quanto segue elencherà, ogni 60s , sullo stesso Terminale, i contenuti della directory Desktop in modo che tu possa sapere se sono state apportate modifiche:

watch -n 60 ls -l ~/Desktop
    
risposta data nux 06.03.2014 - 16:54
74

Puoi anche usare questo comando nel terminale, a parte la risposta di nux:

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

Esempio

while true; do ls; sleep 2; done

Questo comando stamperà l'output di ls a un intervallo di 2 secondi.

Usa Ctrl + C per fermare il processo.

Vi sono alcuni svantaggi di watch

  • Non può utilizzare alcun comando con alias.
  • Se l'output di qualsiasi comando è piuttosto lungo, lo scorrimento non funziona correttamente.
  • C'è qualche problema a impostare intervallo di tempo massimo oltre un determinato valore.
  • watch interpreterà sequenze di colori ANSI che passano caratteri di escape usando l'opzione -c o --color . Ad esempio, l'output di pygmentize funzionerà ma fallirà per ls --color=auto .

Nelle suddette circostanze, questa potrebbe apparire come un'opzione migliore.

    
risposta data souravc 06.03.2014 - 17:00
31

Volevo solo inserire le risposte souravc e nux :

  1. Anche se watch funzionerà perfettamente su Ubuntu, potreste voler evitare che, se volete che il vostro "Unix-fu" sia puro, su FreeBSD per esempio, watch è un comando per "curiosare su un'altra linea tty".
  2. while true; do command; sleep SECONDS; done ha anche un avvertimento: il tuo comando potrebbe essere più difficile da uccidere utilizzando CTR + C . Potresti preferire while sleep SECONDS; do command; done - non solo è più breve, ma anche più facile da interrompere. L'avvertenza è che prima dormirà, quindi eseguirà il comando, quindi dovrai aspettare un po 'di SECONDS prima che si verifichi la prima occorrenza del comando.
risposta data d33tah 08.03.2014 - 16:51
11

Sembra il compito ideale per il daemon cron che consente l'esecuzione di comandi periodici. Esegui il comando crontab -e per iniziare a modificare la configurazione cron dell'utente. Il suo formato è documentato in crontab (5) . Fondamentalmente hai cinque campi separati dal tempo, seguiti da un 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)

Ad esempio, se desideri eseguire uno script Python ogni martedì, alle 11:00:

0 11 * * 1 python ~/yourscript.py

Ci sono anche alcuni nomi speciali che sostituiscono il tempo, come @reboot . Molto utile se è necessario creare una directory temporanea. Dal mio crontab (elencato con crontab -l ):

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

Se stai monitorando il file system, inotifywait è brillante e sicuramente aggiunge meno carico al tuo sistema.

Esempio:

Nel terminale 1st digita questo comando:

$ inotifywait .

Poi nel terminale 2nd , qualsiasi comando che influisce sulla directory corrente,

$ touch newfile

Quindi nel terminale originale inotifywait si sveglierà e segnalerà l'evento

./ CREATE newfile2

O in un ciclo

$ 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.
    
risposta data X Tian 06.03.2014 - 17:35
4

Puoi creare il tuo comando repeat facendo i seguenti passi; credits qui :

Innanzitutto, apri il file .bash_aliases :

$ xdg-open ~/.bash-aliases

In secondo luogo, incolla queste righe nella parte inferiore del file e salva:

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

Terzo, chiudi e riapri il terminale o digita:

$ source ~/.bash_aliases

Et voilà! Ora puoi usarlo in questo modo:

$ repeat 5 echo Hello World !!!

o

$ repeat 5 ./myscript.sh
    
risposta data Blufter 08.08.2014 - 21:38
4

puoi usare crontab. esegui il comando crontab -e e aprilo con il tuo editor di testo preferito, quindi aggiungi questa riga

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

Questo eseguirà il tuo comando ogni 10 minuti

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

Questo eseguirà il comando ogni 4 ore

Un'altra possibile soluzione

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

X numero di volte da ripetere.

Y tempo di attesa da ripetere.

Esempio:

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

Un altro problema con l'approccio "orologio" proposto sopra è che mostra il risultato solo quando il processo è terminato. "data; sleep 58; date" visualizzerà le 2 date solo dopo 59 secondi ... Se avvii qualcosa in esecuzione per 4 minuti, che visualizza lentamente più pagine di contenuto, non lo vedrai realmente.

D'altra parte, la preoccupazione per l'approccio "while" è che non prende in considerazione la durata dell'attività.

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

Con questo, lo script verrà eseguito ogni volta ogni minuto, a volte potrebbe richiedere 1m40. Quindi, anche se un cron sarà in grado di eseguirlo ogni minuto, qui non lo farà.

Quindi, per vedere l'output sulla shell mentre viene generato e attendere il tempo esatto della richiesta, devi guardare l'ora prima, e dopo, e ripetere il ciclo con il tempo.

Qualcosa come:

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

Questo produrrà questo:

Come puoi vedere, il comando viene eseguito ogni 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

Quindi basta sostituire il comando "sleep echo $(( ( RANDOM % 30 ) + 1 )) " con quello che vuoi e che verrà eseguito, sul terminale / shell, esattamente ogni minuto. Se vuoi un altro programma, cambia i "60" secondi con quello che ti serve.

Versione più breve senza le linee di debug:

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
    
risposta data jmspaggi 14.12.2015 - 21:56

Leggi altre domande sui tag