2015-08-07 4 views
2

у меня есть вызов run.sh Баш скрипт, который запускает несколько процессовОтправка SIGTERM всем процессам

#!/bin/bash 
proc1 & 
proc2 & 
proc3 & 
final # this runs until sigterm 

Когда я исполняю run.sh и я отправить SIGTERM в run.sh, я не думаю, что SIGTERM посылается в final, и я не думаю, что он отправляется в proc1, proc2 и proc3. Обратите внимание, что в этом случае это контейнер для докеров, который работает run.sh, а работа docker stop - это способ, которым я пытаюсь отправить SIGTERM.

Что было бы самым простым способом для скрипта bash отправить сигмерм всем процессам, которые он начал? Единственный способ, о котором я могу думать, - это запустить final с &, а затем сделать цикл while в run.sh?

EDIT - я пробовал, хотя, кажется, не работает: В run.sh

#!/bin/bash 
_term() { 
    echo "Caught SIGTERM signal!" 
} 
trap _term SIGTERM 
echo "hi" 
sleep 100000 & 
wait $! 

При работе Docker стоп, я никогда не видел Caught SIGTERM signal!

+0

Вам необходимо пройти вниз '_term' имя функции в виде строки, как:' ловушки «» _term SIGINT' – h3nrik

+0

@ h3nrik Я попытался «_term», до сих пор не работает – K2xL

+1

Ваш скрипт не может запустить обработчик до тех пор, пока «sleep» не выйдет, поскольку он не прерывается.Запустите его в фоновом режиме с помощью 'sleep 100000 &'; то выполняется команда 'wait' и * * может быть прервана для запуска вашего помощника. Кстати, '$!' Не совсем определен в вашем скрипте, потому что вы еще не запускали никаких фоновых команд. – chepner

ответ

-1

Правильно, я бы собрать их всех в массиве и затем отправить сигнал каждому из них по завершении. Я бы использовал что-то вроде awk '{ system("kill -15 " $1)}'.

+1

Do * not * use 'kill -9'. Это для того, чтобы убить багги-программы, так как это не позволяет процессу очищаться после себя. – chepner

+0

Правильно в этом контексте, сигммер или сигман, вероятно, более уместны. Если, конечно, они не ведут себя хорошо, то сигкилл - это билет ... поскольку его нельзя игнорировать. –

1

Вы сказали, что используете этот сценарий в контейнере Docker. Не могли бы вы дать нам более подробную информацию о том, как вы запускаете контейнер и как вызывается run.sh ?.

При вызове docker stop или непосредственно SIGTERM принимает контейнер, содержащийся с PID 1, получит его. Когда ваш run.sh создает дочерние процессы, которые работают в фоновом режиме , он также должен пересылать сигналы им.

Поэтому это не очень хороший подход для создания фоновых дочерних процессов в сценарии bash с &. Использование supervisor было бы хорошей практикой, так как оно правильно обрабатывает сигналы и пересылает их в дочерние процессы без каких-либо дополнительных скриптов.

Кроме того, supervisord не должен запускаться как сам дочерний процесс оболочки. Это может произойти, если вы укажете это в качестве команды контейнера в вашем Dockerfile:

CMD /usr/bin/supervisord 

Вместо этого он должен выглядеть следующим образом:

CMD ["/usr/bin/supervisord"] 

Таким образом, руководитель становится процессом корневым с PID 1 и получит все сигналы правильно и перенаправляет их на дочерние процессы.

+0

Итак, мой run.sh - это CMD, который запускается для контейнера докеров. Но я смущен - почему бы не поймать сигналы с bash на run.sh work (и fyi, я просто попробовал, и это не так) – K2xL

+0

Потому что вам явно нужно будет использовать 'trap' как описано [здесь] (http://veithen.github.io/2014/11/16/sigterm-propagation.html), например. – h3nrik

+0

Также я проверил, что мой запуск run.sh начинается с PID 1 – K2xL

0

Используйте jobs -p, чтобы получить идентификаторы процесса любых фоновых заданий, затем передайте их kill.

trap 'kill $(jobs -p)' TERM 

proc1 & 
proc2 & 
proc3 & 

wait 
Смежные вопросы