web-dev-qa-db-fra.com

Répéter une commande tous les x intervalles de temps dans le terminal?

Comment puis-je répéter une commande à chaque intervalle de temps pour pouvoir exécuter des commandes pour les répertoires vérification ou surveillance?

Il n'y a pas besoin d'un script, j'ai juste besoin d'une simple commande à exécuter dans un terminal.

132
user239745

Vous pouvez utiliser la commande watch, watch est utilisé pour exécuter toute commande spécifiée à intervalles réguliers.

Ouvrez le terminal et tapez:

watch -n x <your command>

changez x pour être le temps en secondes que vous voulez.

Pour obtenir de l'aide supplémentaire sur la commande watch et ses options, exécutez man watch ou visitez ceci Link .

Par exemple: , le suivant liste tous les 60s , de la même manière Terminal, le contenu du répertoire Desktop afin que vous puissiez savoir si des modifications ont été apportées:

watch -n 60 ls -l ~/Desktop
207
nux

Vous pouvez également utiliser cette commande dans terminal, en dehors de la réponse de nux:

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

Exemple

while true; do ls; sleep 2; done

Cette commande imprimera la sortie de ls à un intervalle de 2 secondes.

Utilisation Ctrl+C pour arrêter le processus.

Il y a peu d'inconvénients à watch

  • Il ne peut utiliser aucune commande avec alias.
  • Si le résultat d'une commande est assez long, le défilement ne fonctionne pas correctement.
  • Il y a quelques problèmes à régler intervalle de temps maximum au-delà de certaines valeurs.
  • watch interprétera les séquences de couleurs ANSI en transmettant les caractères d'échappement à l'aide de l'option -c ou --color. Par exemple, la sortie de pygmentize fonctionnera mais échouera pour ls --color=auto.

Dans les circonstances ci-dessus, cela peut sembler une meilleure option.

85
souravc

Je voulais juste me lancer dans les réponses de souravc et nux:

  1. Alors que watchfonctionnera parfaitement sous Ubuntu, vous voudrez peut-être éviter cela si vous voulez que votre "Unix-fu" soit pur - sous FreeBSD par exemple, watch est une commande pour "espionner sur une autre ligne de tty".
  2. while true; do command; sleep SECONDS; done a également une mise en garde - votre commande pourrait être plus difficile à tuer avec CTR + C. Vous voudrez peut-être préférer while sleep SECONDS; do command; done - ce n'est pas seulement plus court, mais aussi plus facile à interrompre. La mise en garde est qu'il va d'abord dormir, puis exécuter votre commande. Vous devrez donc attendre quelques SECONDSavant que la première occurrence de la commande ne se produise.
34
d33tah

Cela semble être la tâche idéale pour le démon cron qui permet d’exécuter des commandes périodiques. Exécutez la commande crontab -e pour commencer à modifier la configuration cron de votre utilisateur. Son format est documenté dans crontab (5) . En gros, vous avez cinq champs liés au temps, séparés par des espaces, suivis d'une commande:

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)

Par exemple, si vous souhaitez exécuter un script Python tous les mardis, 11 heures:

0 11 * * 1 python ~/yourscript.py

Il existe également des noms spéciaux qui remplacent l'heure, par exemple @reboot. Très utile si vous devez créer un répertoire temporaire. Dans ma crontab (répertoriée avec crontab -l):

# Creates a temporary directory for ~/.distcc at boot
@reboot ln -sfn "$(mktemp -d "/tmp/distcc.XXXXXXXX")" "$HOME/.distcc"
11
Lekensteyn

Si vous surveillez le système de fichiers, alors inotifywait est brillant et ajoute certainement moins de charge sur votre système.

Exemple :

Dans 1st terminal, tapez cette commande:

$ inotifywait .

Puis dans 2nd terminal, toute commande qui affecte le répertoire en cours,

$ touch newfile

Puis inotifywait dans le terminal d'origine se réveille et rapporte l'événement

./ CREATE newfile2

Ou en boucle

$ 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.
5
X Tian

vous pouvez utiliser crontab. lancez la commande crontab -e et ouvrez-la avec votre éditeur de texte préféré, puis ajoutez cette ligne

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

Cela lancera votre commande toutes les 10 minutes

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

Cela lancera votre commande toutes les 4 heures

Une autre solution possible

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

X nombre de fois à répéter.

Y temps d'attente pour répéter.

Exemple :

$ echo; for i in $(seq 5); do $cmd "This is echo number: $i"; sleep 1;done
4
Maythux

Vous pouvez créer votre propre commande repeat en procédant comme suit: crédits ici :

Commencez par ouvrir votre fichier .bash_aliases:

$ xdg-open ~/.bash-aliases

Deuxièmement, collez ces lignes au bas du fichier et enregistrez:

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

Troisièmement, fermez et rouvrez votre terminal ou tapez:

$ source ~/.bash_aliases

Et voilà ! Vous pouvez maintenant l'utiliser comme ceci:

$ repeat 5 echo Hello World !!!

ou

$ repeat 5 ./myscript.sh
4
Blufter

L’approche "veille" proposée ci-dessus pose un autre problème: elle n’affiche le résultat que lorsque le processus est terminé. "date; sommeil 58; date" affichera les 2 dates seulement après 59 secondes ... Si vous démarrez quelque chose pendant 4 minutes, il affiche lentement plusieurs pages de contenu, vous ne le verrez pas vraiment.

D'autre part, le problème avec l'approche "tant que" est qu'elle ne prend pas en compte la durée de la tâche.

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

Avec cela, le script s'exécutera toutes les minutes, parfois 1m40. Donc même si un cron sera capable de le lancer toutes les minutes, ici, il ne le fera pas.

Donc, pour voir la sortie sur le Shell telle qu'elle est générée et attendre l'heure exacte de la requête, vous devez regarder l'heure avant et après et boucler avec.

Quelque chose comme:

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

Cela produira ceci:

Comme vous pouvez le constater, la commande s’exécute toutes les minutes:

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

Il suffit donc de remplacer la commande "sleep echo $(( ( RANDOM % 30 ) + 1 ))" par ce que vous voulez et qui sera exécutée, sur le terminal/Shell, exactement chaque minute. Si vous voulez un autre horaire, il suffit de changer les "60" secondes avec tout ce dont vous avez besoin.

Version plus courte sans les lignes de débogage:

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
3
jmspaggi