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
Заявление где-то в вашем сценарии в точке, где вы хотите, чтобы он вступил в силу.
- Нажмите
Ctrl-Z
приостановить выполнение сценария; 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.