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

Je revois 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 arrêter l'set des choses, je presse Control-C. Cela arrête le rsync, mais il continue à passer à l'autre. Dans ce cas, je me rends count de ce qui s'est passé et ensuite, appuyez sur Control-C comme un fou jusqu'à ce que les choses fonctionnent à nouveau.

Existe-t-il un moyen de «réparer» cela. Je le veux donc si j'ai une boucle comme ça, et appuyez sur Control-C, qu'il me renverra à mon shell bash.

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

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

Vous pouvez définir un piège pour Control-C.

 trap command SIGINT 

exécutera la command lorsque Control-C est pressé. Il suffit de mettre la déclaration de piège quelque part dans votre script à un point où vous voulez qu'il entre en vigueur.

Pour étendre la réponse de Dennis, votre code pourrait ressembler à:

 trap "echo Exited!; exit;" SIGINT SIGTERM 

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

Lorsque vous mettez une string de commands entre parenthèses, la string agira comme un process unique et recevra le SIGINT et se terminera lorsque vous appuyez sur CtrlC :

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

Mais! Dans le cas de la command rsync , elle permet de multiples sources, de sorte que le code que vous avez écrit serait mieux écrit:

 rsync -a * example.com:somewhere/ 
  1. Appuyez sur Ctrl-Z pour suspendre le script;
  2. kill %%

Crédits, explications et plus de détails dans cette réponse .

J'ai tendance à mettre une autre command dans ma boucle qui peut facilement être interrompue. Il faut que deux ctrl-C soient pressés.

 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 souhaitez probablement exécuter rapidement. Mais cela fonctionne bien pour d'autres loops, comme celle-ci:

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

Cette boucle searchra à nouveau l'adresse d'exemple à chaque boucle, ce qui est utile si vous surveillez un changement de DNS.