Ré-exécuter continuellement une commande à la fin de Bash

62

J'essaie de trouver un moyen simple de continuer à réexécuter une commande chaque fois qu'elle se termine, pour une raison quelconque (erreur ou autre).

Quelle serait la meilleure façon d'aborder cela?

EDIT: Je n'étais pas assez clair avant. J'ai besoin que la prochaine exécution attende que la précédente se termine.

EDIT 2: Presque toutes les réponses fonctionnent très bien. Je pensais à tort que la plupart des réponses déboucheraient sur le processus ou le ré-exécuter une seule fois, ce qui n’est ni souhaité.


la source
1
Vous n'êtes toujours pas clair. Il serait utile que vous mentionniez le programme que vous exécutez.
Daniel Beck
1
-1 Cette question ne montre aucun effort de recherche, car l'utilisateur a commenté que les réponses ne fonctionnaient pas au lieu d'essayer de faire ce qu'elles suggéraient.
Daniel Beck

Réponses:

39

Cela crée une boucle infinie, s'exécutant commandencore et encore.

while :
    do
        command
done
Dennis
la source
S'il vous plaît voir l'édition à la question d'origine. Je dois continuer à l'exécuter encore et encore, pas seulement une fois.
8
@calcifer Cette réponse fonctionne assez bien. Il y a quelque chose d'inhabituel dans votre programme qu'aucun des quatre utilisateurs ayant répondu à ce jour n'a prévu et que vous avez omis de mentionner.
Daniel Beck
@calcifer c'est une boucle infinie. il se répète jusqu'à la fin des temps (enfin, jusqu'à ce que le script soit terminé de toute façon)
Nate Koppenhaver
1
Mon mauvais, je pensais que cela (et toutes les autres réponses) allait soit renverser le processus, soit le ré-exécuter une seule fois, ce qui n’est ni voulu. Alors oui, cette réponse fonctionne. Merci.
1
version une ligne :,while true; do echo 'Hit CTRL+C'; sleep 1; done grâce à cyberciti.biz/faq/bash-infinite-loop
jk2K
107

La watchcommande répétera une commande pour toujours avec un intervalle spécifié:

watch -n0 <command>

La mise -nà zéro réduit effectivement l'intervalle à zéro (je pense que c'est vraiment 0,1 secondes).

watch offre également l’avantage supplémentaire d’aligner la sortie afin que les modifications visuelles soient facilement visibles, et dispose d’un commutateur pour mettre en évidence les modifications depuis la dernière exécution.

Référence: la page de manuel de la montre :

watch run commande à plusieurs reprises, en affichant sa sortie (le premier écran). Cela vous permet de suivre l'évolution de la sortie du programme. Par défaut, le programme est exécuté toutes les 2 secondes. utilisez -n ou --interval pour spécifier un intervalle différent.

la montre fonctionnera jusqu'à ce qu'elle soit interrompue.

Paul
la source
S'il vous plaît voir l'édition à la question d'origine.
6
Jusqu'à présent, toutes les réponses le font, y compris celui-ci. Linux ne se divisera pas à moins que vous ne le lui demandiez spécifiquement.
Paul
Je ne savais pas ça à propos de fork, merci.
Je ne vois aucune sortie utilisant cette méthode.
Raffi Khatchadourian
@RaffiKhatchadourian Voulez-vous dire que si vous le faites watch lsdans un répertoire contenant des fichiers, vous n'obtenez rien?
Paul
17

Une solution simple serait:

yourcommand; !#

;sépare les commandes, permettant plusieurs commandes sur une seule ligne ( Bash: Lists )

!#indique à bash de "répéter tout ce que j'ai écrit jusqu'à présent dans cette ligne" ( Bash: Event-Designators )

Ciel bleu
la source
1
Désolé, je n'ai pas été assez clair. Je dois continuer à l'exécuter encore et encore, pas seulement une fois.
Merci pour cela, je le cherchais, d'autant plus que yourcommand; !!cela ne semble pas fonctionner avec les commandes de la même ligne !#. À votre santé!
Sdaau
; !#n'a pas fonctionné sur ZSH, il élargit simplement la déclaration en le clonant, cela ne le déclenche pas
revelt
7

Vous pouvez planifier à l’avance pendant l’exécution de la commande (à condition qu’elle ne soit pas interactive) et !!indiquer qui exécutera à nouveau la commande précédente. Cela fonctionne par exemple pendant ping -c 5.


Vous pouvez également définir une fonction dans bash:

function repeat { "$@"; "$@"; }

Pour le persister, stockez-le dans ~/.bashrc.

Ensuite, vous pouvez exécuter votre commande comme ceci:

repeat ping -c5 heise.de

S'il s'agit d'une commande spécifique que vous souhaitez exécuter de manière répétée (et non par exemple une commande), vous pouvez remplacer "$@"cet extrait par votre commande actuelle et nommer la fonction, par exemple repeat_ping.


Pour en faire une boucle infinie, vous pouvez faire ce que @Dennis suggère. Je vous recommande d’ajouter une période d’attente si vous avez l’intention de l’utiliser dans un shell interactif, comme ceci:

function repeat { while 1 ; do "$@" ; sleep 1 ; done; }

Sinon, il est plutôt gênant d’abandonner cette boucle infinie Ctrl-Z.

Daniel Beck
la source
S'il vous plaît voir l'édition à la question d'origine.
6
@calcifer Ces exécutions attendent le retour de l'appel du programme. Votre programme se détache-t-il du shell et revient-il avant qu'il ne quitte?
Daniel Beck
Mon mauvais, je pensais que cela (et toutes les autres réponses) allait soit renverser le processus, soit le ré-exécuter une seule fois, ce qui n’est ni voulu. Alors oui, cette réponse fonctionne. Merci.
4

Donne à une whileboucle une condition booléenne comme suit:

#!/bin/bash

while true; do

    do_something && wait

done

Cela s'exécutera encore et encore jusqu'à ce que bash reçoive un signal pour mettre fin au processus. Habituellement sous la forme de ctrl+c.

Vous pouvez également utiliser la watchcommande pour exécuter un script à plusieurs reprises. Par exemple, une simple horloge dans votre terminal bash watchpeut ressembler à ceci:

$ watch -t -n1 date +%T

L' -toption indique watchde ne pas afficher le titre du processus en cours d'exécution. Cela vous donne une sortie propre de seulement la commande qui est répétée. L' -n1option indique à la montre de se répéter toutes les nsecondes. Dans ce cas, -n1seront des intervalles de 1seconde. Ensuite, la date +%Tcommande affiche l'heure au moment de l'achèvement de la commande. Cette commande vous donnera une horloge active dans votre terminal.

Et puis une autre méthode qui ne figure dans aucune des autres réponses serait un appel de fonction infini.

do_something() { do_something }; do_something && wait

Ceci est essentiellement identique à la whileboucle booléenne utilisant uniquement des appels de fonction récursifs.

(edit) Pour garder les ressources de votre machine à l'esprit, j'ai ajouté le && waitafin que, chaque fois qu'un processus est exécuté, les boucles "attendent" que le processus se termine avec le statut de sortie 0 avant la prochaine itération. Ceci est utile dans un script shell interactif.


la source
1
Il y a un whileexemple de boucle mais il n'utilise pas de truesyntaxe booléenne . Il y a un watchexemple mais cela ne donne pas beaucoup de syntaxe utile. Je les expose pour qui que ce soit qui peut aider. Je voulais leur donner une utilité pratique. La whileboucle booléenne peut également être exécutée falseet ne pas l'exécuter tant qu'une condition fausse n'est pas remplie. C'est assez pratique.
1
@ Spittin'IT Ajout d'une méthode qui n'est pas utilisée dans d'autres réponses pour votre commodité.
Assez juste et je comprends ... Je faisais juste un commentaire alors que je passais dans le module de revue mais bon montage et suivi !!
Pimp Juice IT
Comment ifcontinuer à se ré-exécuter?
Kamil Maciorowski
Bon point Kamil. J'ai oublié de le faire lol récursif. Corrigé en édition en utilisant une fonction s'appelant dans l' ifinstruction
0

C'est une autre méthode que j'utilise pour répéter une commande dans bash. Cela peut paraître ridicule à certains car il ne s’agit pas d’écrire un script et peut être connu de beaucoup. Mais je pense que cela vaut la peine d’être mentionné car c’est rapide et convivial, dans le sens où il n’ya pas beaucoup de syntaxe à retenir. Je n'ai testé cela que dans gnome-terminal d'Ubuntu et d'autres terminaux pourraient ne pas le supporter.

  1. Entrez la commande dans le terminal une fois.
  2. Sélectionnez la commande incluant le caractère de nouvelle ligne avec la souris.
  3. Copiez la sélection en utilisant Ctrl-Inser ou en utilisant le menu contextuel (généralement accessible avec un clic droit).
  4. Utilisez Maj-Insérer pour coller autant de fois que vous le souhaitez pour exécuter la commande.

Vous n'avez pas à attendre pour coller jusqu'à ce que chaque commande se termine. Les commandes collées entrent dans une file d'attente et s'exécutent les unes après les autres.

Jayadeepk
la source
0

Je me sens énervé aujourd'hui.

Lire l’un des flux infinis et le diriger vers xargs

cat /dev/zero | xargs --null echo hello there

Si vous avez besoin de faire une petite pause, vous devrez probablement exécuter sh

cat /dev/zero | xargs --null sh -c "echo hello there && sleep 3"
Jefferey Cave
la source