Почему моя ловушка не срабатывает?

Учитывая сценарий, что echo при получении сигнала SIGSTOP или SIGHUP :

 $cat test.sh function clean_up { echo "cleaning up!" } echo 'starting!' trap clean_up SIGSTOP SIGHUP sleep 100 

Я запустил его в фоновом режиме:

 $./test.sh > output & [4] 42624 

Затем я убил его с -1 , т.е. SIGHUP

 $kill -1 42624 

Но trap не работала так, как я ожидал, т.е. output файл не cleaning up! в его содержании.

 $cat output starting! 

Что случилось?

  • Помимо USR1 и USR2, какие сигналы можно безопасно использовать для пользовательского прерывания поведения? (в python)
  • SIGINT не очищается в "$ {FUNCNAME }"
  • Почему различное поведение захвата EXIT vs INT
  • Может ли Ctrl + C отправить сигнал SIGINT нескольким процессам?
  • убийство подпроцессов и ловушек
  • Невозможно переписать команду «trap» для SIGTSTP, SIGTTIN и SIGTTOU
  • Дайте группе право отправлять сигналы убийства
  • Как сигналы работают внутри страны?
  • 3 Solutions collect form web for “Почему моя ловушка не срабатывает?”

    На самом деле он печатал, но вам нужно подождать 100 секунд, чтобы увидеть результат.

    Ты сказал:

     $./test.sh > output & [4] 42624 

    Если вы проверите ps aux , вы получите нечто похожее на:

     xiaobai 42624 0.0 0.1 118788 5492 pts/3 S 04:07 0:00 /bin/bash xiaobai 42626 0.0 0.0 108192 668 pts/3 S 04:07 0:00 sleep 100 

    Ваш основной процесс скрипта / bin / bash, PID 42624 все еще ждет завершения сна 100. Даже основной процесс получил сигнал 1, он должен сначала дождаться sleep 100 , после чего его очередь выполнить свою задачу, то есть echo "cleaning up!" ,

    Вы можете заставить процесс сна стать фоновым процессом. В этом случае процесс скрипта может выполнять echo "cleaning up!" не дожидаясь sleep process , тогда и только тогда, когда процесс скрипта еще не завершен.

    Мы можем доказать концептуальный (т.е. сценарий ожидания sleep перед сигналом управления) через этот скрипт:

     function clean_up { echo "cleaning up!" } echo 'starting!' trap clean_up SIGHUP sleep 5000 & echo 1 sleep 20 echo 2 sleep 10 echo 3 

    Выполните этот сценарий с помощью ./test.sh > output как обычно, затем используйте ps aux для определения PID /bin/bash PID 23311, затем выполните команду kill -1 23311 . В то же время выходим cat output чтобы знать сцену, то есть когда скрипт входит в sleep 20 после эха 1, отправьте kill -1 23311 , теперь подождите, пока выйдет 2, вы заметите, что «очистка» была напечатана вместе до 2. Наконец, это поворот echo 3 и выход сценария.

     $ cat output starting! 1 cleaning up! 2 3 $ 

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

    История становится интересной, с вашим оригинальным сценарием, что, если вы kill -1 PID_of_sleep_100 ?

    Он выйдет из всех процессов без печати, потому что процесс сна не возвращает процесс SIGHUP в сценарий.

    Таким образом, есть решение вашей задачи, вы можете kill -1 PPID (процесс скрипта), чтобы подтвердить SIGHUP на процесс скрипта, а затем kill -1 PID (процесс сна). Теперь процесс скрипта будет выполнять обработчик SIGHUP перед выходом, счастливый взлом 🙂

    Не все сигналы одинаковы, например, SIGKILL не позволяет ловушке . Если вы убьете -9 процесс сценария, процесс спящего режима все равно будет запущен, а его родительский PID станет 1 (отметьте ps -ef ).

    [ОБНОВИТЬ]:

    Обычно kill -N script_PID будет убивать непосредственно скрипт, если сигнал N не ловушка в вашем скрипте . Но будьте осторожны с SIGINT, kill -2 script_PID не будет напрямую убивать, даже если ваш скрипт не заманивает его. Ваш скрипт будет ждать вашего дочернего процесса (например, sleep 10). Теперь предположим, что вы выполняете несколько kill в script_PID, то есть kill -2 script_PID И kill -user-defined_trap_N script_PID , затем:

    1. Если сон возвращается нормально после ожидания в течение 10 секунд или убивает по сигналу, отличному от 2 , ваш сценарий будет игнорировать кешированный сигнал 2 при возврате, а затем выполнить функцию user-defined_trap_N.
    2. Но если сон убивает по сигналу 2 , тогда ваш скрипт будет выполнять встроенный обработчик SIGINT при возврате, а затем убивать напрямую без выполнения user-defined_trap_N.

    Страница man для состояний bash

    Если bash ожидает завершения команды и получает сигнал, для которого установлена ​​ловушка, ловушка не будет выполняться до тех пор, пока команда не завершится.

    В вашем примере trap не будет выполняться до завершения sleep 100 .

    trap работает с номерами сигналов (т.е. trap clean_up 1 ) или с именами без префикса «sig» (т.е. trap clean_up HUP ).

    Кроме того, SIGSTOP не может быть захвачен .

    Linux и Unix - лучшая ОС в мире.