В каком порядке я должен посылать сигналы для постепенного завершения процессов?
В комментарии к этому ответу на другой вопрос комментатор говорит:
не используйте kill -9 без крайней необходимости! SIGKILL не может быть пойман в ловушку, поэтому убитая программа не может выполнить какие-либо процедуры завершения работы, например, для удаления временных файлов. Сначала попробуйте HUP (1), затем INT (2), затем QUIT (3)
Я согласен в принципе о SIGKILL
, но остальное для меня новость. Учитывая, что сигнал по умолчанию отправляется kill
является SIGTERM
Я бы ожидал, что это наиболее ожидаемый сигнал для постепенного отключения произвольного процесса. Кроме того, я видел SIGHUP
используется по незавершенным причинам, например, для того, чтобы сказать демону "перечитайте файл конфигурации". И мне кажется, что SIGINT
(то же самое прерывание, которое вы обычно получаете с помощью Ctrl-C, верно?) не так широко поддерживается, как должно быть, или завершается довольно неблагодарно.
При условии SIGKILL
последнее средство - какие сигналы и в каком порядке следует отправлять в произвольный процесс, чтобы отключить его как можно более изящно?
Пожалуйста, подкрепите свои ответы подтверждающими фактами (помимо личных предпочтений или мнений) или ссылками, если можете.
Примечание: меня особенно интересуют лучшие практики, которые включают рассмотрение bash/Cygwin.
Редактировать: Пока что никто не упоминает INT или QUIT, и есть ограниченное упоминание HUP. Есть ли какая-либо причина, чтобы включать их в упорядоченный процесс убийства?
7 ответов
SIGTERM сообщает приложению о прекращении. Другие сигналы сообщают приложению другие вещи, которые не связаны с отключением, но иногда могут иметь такой же результат. Не используйте их. Если вы хотите, чтобы приложение закрылось, сообщите об этом. Не давайте этому вводящим в заблуждение сигналов.
Некоторые люди считают, что разумный стандартный способ завершить процесс - отправить ему множество сигналов, таких как HUP, INT, TERM и, наконец, KILL. Это нелепо. Правильный сигнал для завершения - это SIGTERM, и если SIGTERM не завершает процесс мгновенно, как вы могли бы предпочесть, то это потому, что приложение выбрало обработку сигнала. Это означает, что у него есть очень веская причина не прекращать работу немедленно: он должен выполнить работу по очистке. Если вы прервете эту очистку работой с другими сигналами, вы не узнаете, какие данные из памяти еще не сохранены на диске, какие клиентские приложения остались зависшими или прерываете ли вы их "в середине предложения", что фактически приводит к повреждению данных.
Для получения дополнительной информации о реальном значении сигналов см. Sigaction (2). Не путайте "Действие по умолчанию" с "Описание", это не одно и то же.
SIGINT используется для сигнализации интерактивного "прерывания клавиатуры" процесса. Некоторые программы могут обрабатывать ситуацию особым образом для пользователей терминалов.
SIGHUP используется, чтобы сигнализировать, что терминал исчез и больше не смотрит на процесс. Это все. Некоторые процессы предпочитают отключаться в ответ, как правило, потому что их работа не имеет смысла без терминала, некоторые предпочитают делать другие вещи, такие как перепроверять файлы конфигурации.
SIGKILL используется для принудительного удаления процесса из ядра. Он особенный в том смысле, что фактически он не является сигналом для процесса, а интерпретируется ядром напрямую.
Не посылай SIGKILL. SIGKILL, конечно, никогда не должен посылаться сценариями. Если приложение обрабатывает SIGTERM, на очистку может потребоваться секунда, это может занять минуту, это может занять час. В зависимости от того, что приложение должно быть сделано, прежде чем оно будет готово к концу. Любая логика, которая "предполагает" последовательность очистки приложения, занимает достаточно много времени и требует быстрого или SIGKILLed после X секунд, просто неправильно.
Единственная причина, по которой приложению понадобится SIGKILL для завершения, - это если что-то вышло из строя во время последовательности очистки. В этом случае вы можете открыть терминал и SIGKILL его вручную. Кроме того, единственная причина, по которой вы что-то делаете SIGKILL, заключается в том, что вы ХОТИТЕ предотвратить его очистку.
Несмотря на то, что полмира слепо посылает SIGKILL через 5 секунд, это все равно ужасно неправильно.
Краткий ответ: Отправить SIGTERM
30 секунд спустя SIGKILL
, То есть отправить SIGTERM
, подождите немного (это может варьироваться от программы к программе, вы, возможно, знаете свою систему лучше, но достаточно 5–30 секунд. При выключении машины вы можете увидеть, что она автоматически ждет до 13:30. Почему спешка, в конце концов?), то отправьте SIGKILL
,
Разумный ответ: SIGTERM
, SIGINT
, SIGKILL
Этого более чем достаточно. Весьма вероятно, что процесс закончится раньше SIGKILL
,
Длинный ответ: SIGTERM
, SIGINT
, SIGQUIT
, SIGABRT
, SIGKILL
Это не нужно, но, по крайней мере, вы не вводите в заблуждение процесс, касающийся вашего сообщения. Все эти сигналы означают, что вы хотите, чтобы процесс прекратил работу и завершил работу.
Независимо от того, какой ответ вы выберете из этого объяснения, имейте это в виду!
Если вы отправляете сигнал, который означает что-то другое, процесс может обработать его различными способами (с одной стороны). С другой стороны, если процесс не обрабатывает сигнал, в конце концов, не имеет значения, что вы отправляете, процесс все равно завершится (если, конечно, действие по умолчанию завершается).
Итак, вы должны думать как программист. Не могли бы вы написать код обработчика функции, скажем, SIGHUP
выйти из программы, которая соединяется с чем-то, или вы бы зациклились, чтобы попытаться соединиться снова? Это главный вопрос здесь! Вот почему важно просто отправлять сигналы, которые означают, что вы намерены.
Почти глупый длинный ответ:
Таблица ниже содержит соответствующие сигналы и действия по умолчанию, если программа не обрабатывает их.
Я заказал их в порядке, который я предлагаю использовать (кстати, я предлагаю вам использовать разумный ответ, а не этот здесь), если вам действительно нужно попробовать их все (было бы интересно сказать, что стол упорядочен с точки зрения разрушения, которые они могут вызвать, но это не совсем верно).
Сигналы со звездочкой (*) НЕ рекомендуются. Важно то, что вы никогда не узнаете, для чего это запрограммировано. Специально SIGUSR
! Это может запустить апокалипсис (это бесплатный сигнал для программиста делать все, что он / она хочет!). Но, если не обработано ИЛИ в маловероятном случае, когда оно обрабатывается для завершения, программа будет завершена.
В таблице сигналы с параметрами по умолчанию для завершения и создания дампа ядра остаются в конце, непосредственно перед SIGKILL
,
Signal Value Action Comment
----------------------------------------------------------------------
SIGTERM 15 Term Termination signal
SIGINT 2 Term Famous CONTROL+C interrupt from keyboard
SIGHUP 1 Term Disconnected terminal or parent died
SIGPIPE 13 Term Broken pipe
SIGALRM(*) 14 Term Timer signal from alarm
SIGUSR2(*) 12 Term User-defined signal 2
SIGUSR1(*) 10 Term User-defined signal 1
SIGQUIT 3 Core CONTRL+\ or quit from keyboard
SIGABRT 6 Core Abort signal from abort(3)
SIGSEGV 11 Core Invalid memory reference
SIGILL 4 Core Illegal Instruction
SIGFPE 8 Core Floating point exception
SIGKILL 9 Term Kill signal
Тогда я бы предложил для этого почти глупого длинного ответа: SIGTERM
, SIGINT
, SIGHUP
, SIGPIPE
, SIGQUIT
, SIGABRT
, SIGKILL
И, наконец,
Определенно глупый длинный длинный ответ:
Не пытайтесь сделать это дома.
SIGTERM
, SIGINT
, SIGHUP
, SIGPIPE
, SIGALRM
, SIGUSR2
, SIGUSR1
, SIGQUIT
, SIGABRT
, SIGSEGV
, SIGILL
, SIGFPE
и если ничего не получалось, SIGKILL
,
SIGUSR2
надо судить раньше SIGUSR1
потому что нам лучше, если программа не обрабатывает сигнал. И это гораздо более вероятно для него справиться SIGUSR1
если он обрабатывает только один из них.
Кстати, убийство: это не так, чтобы отправить SIGKILL
к процессу, как указано в другом ответе. Ну, подумайте, что происходит, когда вы отправляете shutdown
команда? Будет пытаться SIGTERM
а также SIGKILL
только. Почему вы думаете, что это так? А зачем вам любые другие сигналы, если сам shutdown
Команда использует только эти два?
Теперь вернемся к длинному ответу, это хороший вкладчик:
for SIG in 15 2 3 6 9 ; do echo $SIG ; echo kill -$SIG $PID || break ; sleep 30 ; done
Он спит в течение 30 секунд между сигналами. Зачем еще вам нужен oneliner?;)
Также рекомендуется: попробуйте только с сигналами 15 2 9
из разумного ответа.
безопасность: удалить второй echo
когда ты будешь готов идти. Я называю это своим dry-run
для лайнеров. Всегда используйте это, чтобы проверить.
Скрипт убивает грациозно
На самом деле, я был настолько заинтригован этим вопросом, что решил создать небольшой сценарий, чтобы сделать это. Пожалуйста, не стесняйтесь скачать (клонировать) это здесь:
GitHub ссылка на хранилище Killgracefully
Как правило, вы бы отправили SIGTERM
По умолчанию убить. По умолчанию это причина. Только если программа не закрывается за разумное время, вы должны прибегнуть к SIGKILL
, Но обратите внимание, что с SIGKILL
программа не имеет возможности убирать вещи и данные могут быть повреждены.
Что касается SIGHUP
, HUP
расшифровывается как "зависание" и исторически означало, что модем отключен. По сути это эквивалентно SIGTERM
, Причина, по которой демоны иногда используют SIGHUP
перезапустить или перезагрузить конфигурацию, если демоны отсоединяются от любых управляющих терминалов, так как демон не нуждается в них и поэтому никогда не получит SIGHUP
таким образом, этот сигнал считался "освобожденным" для общего пользования. Не все демоны используют это для перезагрузки! Действие по умолчанию для SIGHUP - завершить, и многие демоны ведут себя таким образом! Так что вы не можете идти вслепую, отправляя SIGHUP
с демонами и ожидая, что они выживут.
Редактировать: SIGINT
вероятно, неуместно завершать процесс, так как он обычно привязан к ^C
или какой-либо другой параметр терминала для прерывания программы. Многие программы фиксируют это для своих собственных целей, поэтому достаточно часто, чтобы это не работало. SIGQUIT
обычно по умолчанию создается дамп ядра, и если вы не хотите, чтобы файлы ядра лежали вокруг, это также не является хорошим кандидатом.
Резюме: если вы отправите SIGTERM
и программа не умирает в течение вашего срока, затем отправьте его SIGKILL
,
SIGTERM
фактически означает отправку заявления с сообщением: " будь так добр и покончишь с собой ". Он может быть перехвачен и обработан приложением для запуска кода очистки и завершения работы.
SIGKILL
не может быть захвачено приложением. Приложение убивается ОС без шансов на очистку.
Это типично для отправки SIGTERM
сначала поспи немного, потом пошли SIGKILL
,
Со всеми обсуждениями здесь не было предложено никакого кода. Вот мое мнение:
#!/bin/bash
$pid = 1234
echo "Killing process $pid..."
kill $pid
waitAttempts=30
for i in $(seq 1 $waitAttempts)
do
echo "Checking if process is alive (attempt #$i / $waitAttempts)..."
sleep 1
if ps -p $pid > /dev/null
then
echo "Process $pid is still running"
else
echo "Process $pid has shut down successfully"
break
fi
done
if ps -p $pid > /dev/null
then
echo "Could not shut down process $pid gracefully - killing it forcibly..."
kill -SIGKILL $pid
fi
- SIGTERM эквивалентно "нажатию на" X "" в окне.
- SIGTERM - это то, что Linux использует в первую очередь, когда он выключается.
HUP звучит как мусор для меня. Я отправил бы его, чтобы демон пересмотрел его конфигурацию.
SIGTERM может быть перехвачен; у ваших демонов может быть код очистки, который он запускает при получении этого сигнала. Вы не можете сделать это для SIGKILL. Таким образом, с SIGKILL вы не предоставляете автору демона никаких опций.
Подробнее об этом в Википедии