Bash Loop - Как остановить цикл, когда я нажимаю Control-C внутри команды?

Я Rsyncing несколько каталогов. У меня открыт терминал Bash, и я выполняю что-то вроде этого:

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

Однако, если я хочу остановить все это, я нажимаю Control-C. Это останавливает rsync, но затем продолжает идти к следующему. В этом случае я понимаю, что произошло, а затем просто нажимаю Control-C, как сумасшедший, пока все снова не заработает.

Есть ли какой-нибудь способ это исправить. Я хочу, чтобы, если у меня был такой цикл, и я нажал Control-C, он вернул меня в оболочку bash.

6 ответов

Решение
for DIR in * ; do rsync -a $DIR example.com:somewhere/ || break; done

Это также приведет к выходу из цикла, если по какой-либо причине отдельный прогон rsync завершится неудачно.

Чтобы расширить ответ Дениса, ваш код может выглядеть так:

trap "echo Exited!; exit;" SIGINT SIGTERM

Для рабочего примера (который включает в себя rsync), посмотрите http://gist.github.com/279849.

Вы можете установить ловушку для Control-C.

trap <command> SIGINT

выполнит command когда Control-C нажата. Просто положи trap Заявление где-то в вашем сценарии в точке, где вы хотите, чтобы он вступил в силу.

  1. Нажмите Ctrl-Z приостановить выполнение сценария;
  2. kill %%

Кредиты, объяснения и более подробную информацию в этом ответе.

Когда вы помещаете строку команд в круглые скобки, строка будет действовать как отдельный процесс, получит SIGINT и завершится, когда вы нажмете Ctrl-C:

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

Но! В случае с rsync Команда, она допускает несколько источников, поэтому написанный вами код будет написан лучше:

rsync -a * example.com:somewhere/

Я склонен помещать в свой цикл другую команду, которая может быть легко прервана. Это требует двух Ctrl-C для нажатия.

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

Это не очень хорошее решение для этого rsync, который вы, вероятно, хотите запустить быстро. Но это хорошо работает для других циклов, как этот:

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

Этот цикл будет пересматривать адрес example.com каждый раз в цикле, что полезно, если вы наблюдаете за изменением DNS.

Другие вопросы по тегам