Bash循环 – 如何停止循环,当我按Control-C里面的命令?

我正在rsyncing几个目录。 我有一个bashterminal打开,正在执行这样的事情:

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

但是如果我想停止整个事情,我按Control-C。 这停止了​​rsync,但它继续下一个。 在这种情况下,我意识到发生了什么事情,然后像疯子一样按Control-C,直到事情再次起作用。

有没有办法来“解决”这个。 我想要它,所以如果我有一个这样的循环,并按下Control-C,它会将我返回到我的bash shell。

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

这也将退出循环,如果一个人的rsync运行由于某种原因失败。

您可以为Control-C设置陷阱。

 trap command SIGINT 

将在Control-C被按下时执行该命令。 只要在脚本中的某个地方放置陷阱语句,就可以使其生效。

为了扩大丹尼斯的答案,你的代码可能看起来像:

 trap "echo Exited!; exit;" SIGINT SIGTERM 

对于一个工作的例子(这涉及到rsync),请查看http://gist.github.com/279849

当你把一串命令放在圆括号内时,这个string将作为一个单独的进程来运行,当你点击CtrlC时会收到SIGINT并终止。

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

但! 在rsync命令的情况下,它允许多个来源,所以你写的代码可以写得更好:

 rsync -a * example.com:somewhere/ 
  1. Ctrl-Z暂停脚本;
  2. kill %%

信用,解释和更多的细节在这个答案 。

我倾向于把另一个命令放在我的循环中,很容易被打断。 它需要两个ctrl-C被按下。

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

对于这个rsync来说,这不是一个很好的解决scheme,你可能想要快速运行。 但是对于其他循环来说,它确实很好,比如:

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

这个循环将每次通过循环重新查找example.com的地址,如果您正在观察DNS更改,这将非常有用。