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


35

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

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

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

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


6
Ответ Денниса верен, но если вы этого не сделали, вам не нужно «нажимать на него, как на сумасшедшего», просто держите его и позвольте клавиатуре повторить его :-)
Кайл Брандт

Я всегда просто удерживаю Cntl-C, в целом работает нормально.
Скотт Алан Миллер

Ответы:


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

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


4
Дополнительный совет: если вы находитесь во вложенном цикле и хотите полностью завершить, используйте break 2(или замените «2» на количество вложенных циклов, которое вы хотите завершить).
Долан Антенуччи

26

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

trap "echo Exited!; exit;" SIGINT SIGTERM

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


Спасибо, это общее решение, которое сработало для меня
wi1


7
  1. Нажмите, Ctrl-Zчтобы приостановить сценарий;
  2. kill %%

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


Это здорово, потому что работает «постфактум», когда вы хотите прервать длительный цикл, который вы уже запустили.
Ник Маттео

лучший ответ, спасибо!
Костанос

6

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

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

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

rsync -a * example.com:somewhere/

0

Я склонен помещать в свой цикл другую команду, которая может быть легко прервана. Это требует двух 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.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.