Bash Loop - Comment arrêter la boucle lorsque j'appuie sur Control-C dans une commande?


35

Je suis en train de resynchroniser quelques annuaires. J'ai un terminal bash ouvert et j'exécute quelque chose comme ceci:

for DIR in * ; do rsync -a $DIR example.com:somewhere/ ; done

Cependant, si je veux tout arrêter, j'appuie sur Control-C. Cela arrête le rsync, mais ensuite il continue à aller au suivant. Dans ce cas, je réalise ce qui s’est passé et appuie ensuite sur Control-C comme un fou jusqu’à ce que tout fonctionne à nouveau.

Y at-il un moyen de "réparer" cela. Je le veux, donc si j'ai une boucle comme celle-là et que j'appuie sur Ctrl-C, cela me ramènera à mon shell bash.


6
La réponse de Dennis est la bonne, mais si vous ne le faites pas, vous n'avez pas à le presser comme un fou, tenez-le et laissez le clavier répéter le traitement :-)
Kyle Brandt

Je tiens toujours juste Cntl-C, fonctionne généralement bien.
Scott Alan Miller

Réponses:


33
for DIR in * ; do rsync -a $DIR example.com:somewhere/ || break; done

Cela permettra également de quitter la boucle si une exécution individuelle de rsync échoue pour une raison quelconque.


4
Conseil supplémentaire: si vous êtes dans une boucle imbriquée et que vous souhaitez terminer complètement, utilisez break 2(ou remplacez "2" par le nombre de boucles imbriquées que vous souhaitez terminer).
Dolan Antenucci

26

Pour développer la réponse de Dennis, votre code pourrait ressembler à ceci:

trap "echo Exited!; exit;" SIGINT SIGTERM

Pour un exemple pratique (impliquant rsync), consultez http://gist.github.com/279849 .


Merci, ceci est une solution générique qui a fonctionné pour moi
wi1

25

Vous pouvez définir une interruption pour Control-C.

trap <command> SIGINT

s'exécutera commandlorsque Control-C sera enfoncé. Il suffit de placer la trapdéclaration quelque part dans votre script à un point où vous souhaitez qu'elle devienne effective.



6

Lorsque vous mettez une chaîne de commandes entre parenthèses, la chaîne agira comme un processus unique, recevra le SIGINT et se terminera lorsque vous frapperez Ctrl- C:

(for DIR in * ; do rsync -a $DIR example.com:somewhere/ ; done)

Mais! Dans le cas de la rsynccommande, elle autorise plusieurs sources. Le code que vous avez écrit serait ainsi mieux écrit:

rsync -a * example.com:somewhere/

0

J'ai tendance à mettre une autre commande dans ma boucle qui peut facilement être interrompue. Il faut appuyer sur deux touches Ctrl-C.

for DIR in * ; do rsync -a $DIR example.com:somewhere/ ; sleep 1 ; done

Ce n'est pas une excellente solution pour ce rsync, que vous voudrez probablement exécuter rapidement. Mais cela fonctionne bien pour d'autres boucles, comme celle-ci:

while true ; do ping -c 10 example.com ; sleep 1 ; done

Cette boucle recherchera à chaque fois l'adresse de example.com à travers la boucle, ce qui est utile si vous surveillez un changement DNS.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.