подтвержденный выход с ловушкой

Я пытаюсь захватить сигнал Ctrl+C запрашивая подтверждение у пользователя. Улавливающая часть работает нормально. Но как только сигнал попадает в ловушку, он не возвращается к нормальному исполнению. Вместо этого он выходит из сценария. Как заставить его возобновить выполнение, когда пользователь нажимает «нет».

вот мой код

 hell() { echo "Do you want to quit? Press 1 for yes and 0 for no"; read n; if [ $n == 1 ]; then exit 1; fi } trap "hell" SIGINT find / 

One Solution collect form web for “подтвержденный выход с ловушкой”

Что происходит

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

Если код в ловушке возвращается (т. Е. Не вызывает exit ), выполнение продолжается с помощью команды после той, которая была прервана сигналом. Здесь, после того, как команда find наступает в конце скрипта, так что скрипт выйдет немедленно. Но вы можете увидеть разницу между входом 0 и 1, добавив еще одну команду:

 find / echo "find returned $?" 

Способ делать то, что вы хотите (но, вероятно, не следует делать)

Ты можешь делать, что хочешь; но эта часть моего ответа больше связана с открытием программирования оболочки, чем с решением реальной проблемы.

  • В качестве элемента дизайна перезапускаемый сигнал – это не то, что вы обычно ожидаете в виде относительно простых программ, которые обычно выполняются в сценариях оболочки. Ожидается, что Ctrl + C убьет скрипт.
  • Как вы увидите ниже, в любом случае он немного расширяет возможности оболочки.

Если вы хотите избежать find , вам нужно запустить его в фоновом режиме : find / & . Затем используйте wait builtin, чтобы дождаться, когда он выйдет нормально. Сигнал прерывает функцию wait , которую вы можете запускать в цикле, пока не получите сигнал, который хотите передать. Затем используйте kill чтобы убить задание.

 hell () { echo "Do you want to quit? Press 1 for yes and 0 for no" read n if [ "$n" = 1 ]; then # Kill the job if it's running, then exit if [ -n "$job_pid" ]; then kill $job_pid; fi exit 1 fi } job_pid= trap "hell" SIGINT # Start a demo job in the background for i in 1 2 3 4 5; do date; sleep 1; done & job_pid=$! # Call wait in a loop; wait will return 0 if the job exits, and 128+$signum if interrupted by a signal. while ! wait; do echo "resuming wait" done job_pid= echo last exit code: $? 

Существуют ограничения этого подхода в оболочке:

  • Состояние гонки: если вы нажмете Ctrl + C сразу после завершения задания, но до job_pid= обработчик сигнала попытается убить $jobpid , но процесс больше не существует (даже как зомби, потому что wait уже заработал его), и идентификатор процесса может быть повторно использован другим процессом. Это не легко устранить в оболочке (возможно, установив обработчик для SIGCHLD ?).
  • Если вам нужен статус возврата из задания, вам нужно использовать форму wait $job_pid . Но тогда вы не можете отличить « wait было прервано сигналом» от «задание было убито сигналом» (или от «прекращенного по своему усмотрению задания с возвратным статусом ≥128», но это общий факт в программирование оболочки).
  • Это не будет распространяться легко, если вообще на несколько подзаголовков. Обратите внимание, что поведение ловушек и сигналов часто удивительно, когда вы выходите за рамки основ большинства реализаций оболочки (только ksh делает это хорошо).

Чтобы преодолеть эти ограничения, используйте более привлекательный язык, например Perl или Python.

  • Создать мигающий текст с эхо-символами
  • Как я могу удалить все файлы в папку, к которой не было доступа за определенное время?
  • Передача значений в скрипт
  • избегать множественных труб, поврежденных из-за отсутствия команды
  • Имя переменной массива Bash eval
  • Как создать zip-каталогов -mtime -150
  • Извлечение информации из имени файла и содержимого файла
  • Автоматизировать процедуру ввода двоичного файла
  • Оболочечная среда для двоичной обработки
  • Экспорт паролей из диспетчера паролей `pass`
  • Сравните подобие или расстояние levenshtein между каждой парой линий внутри файла?
  • gnome-terminal cmd оставляют процессы открытыми после закрытия родительского окна
  • Linux и Unix - лучшая ОС в мире.