В чем различия сигналов SIGKILL и SIGTERM?

Ответ

SIGTERM (Signal 15, kill по умолчанию) и SIGKILL (Signal 9, kill -9) — это сигналы операционной системы, используемые для управления процессами, но они имеют принципиальные различия в поведении:

  • SIGTERM (Terminate Signal)

    • Тип: "Вежливый" запрос на завершение.
    • Перехватываемость: Процесс может перехватить этот сигнал и обработать его.
    • Поведение: Дает процессу возможность выполнить операции по очистке: сохранить данные, закрыть файлы, освободить ресурсы, корректно завершить дочерние процессы.
    • Цель: Обеспечить грамотное завершение работы без потери данных или повреждения состояния.
  • SIGKILL (Kill Signal)

    • Тип: "Жесткое" принудительное завершение.
    • Перехватываемость: Процесс не может перехватить или игнорировать этот сигнал.
    • Поведение: Операционная система немедленно и принудительно завершает процесс. Процесс не получает возможности выполнить какие-либо действия по очистке.
    • Цель: Гарантированное завершение процесса, когда он не реагирует на другие сигналы.

Ключевое отличие: Возможность процесса обработать сигнал и выполнить очистку.

Пример обработки SIGTERM в Python:

import signal
import sys
import time

def handle_sigterm(signum, frame):
    print(f"[{time.time():.2f}] Получен SIGTERM ({signum}). Начинаю корректное завершение...")
    # Здесь можно выполнить очистку: закрыть соединения, сохранить состояние и т.д.
    time.sleep(1) # Имитация работы по очистке
    print(f"[{time.time():.2f}] Очистка завершена. Выход.")
    sys.exit(0)

# Регистрируем обработчик для SIGTERM
signal.signal(signal.SIGTERM, handle_sigterm)

print(f"[{time.time():.2f}] Процесс запущен. Ожидаю сигналы...")
try:
    while True:
        time.sleep(5) # Имитация полезной работы
except KeyboardInterrupt:
    print(f"[{time.time():.2f}] Получен KeyboardInterrupt (Ctrl+C), выход.")
    sys.exit(0)

Если отправить kill <PID> (что по умолчанию отправляет SIGTERM) этому скрипту, он выведет сообщение о получении сигнала и корректно завершится. Если отправить kill -9 <PID> (SIGKILL), процесс будет немедленно остановлен без вывода сообщений обработчика.

Рекомендация: Всегда следует сначала пытаться завершить процесс с помощью SIGTERM. Если процесс не реагирует в течение разумного времени (например, 5-10 секунд), тогда можно использовать SIGKILL как крайнюю меру. Это минимизирует риск потери данных и повреждения состояния системы.

Ответ 18+ 🔞

А, слушай, вот тебе история про то, как процессы в операционке дохнут. Есть два главных палача: SIGTERM и SIGKILL. И они, блядь, как небо и земля, как вежливый официант и ОМОН с дубинкой.

SIGTERM (Сигнал 15, обычный kill) — это как вежливый стук в дверь.

  • Суть: "Дружище, пора закругляться, пожалуйста".
  • Можно ли его послать?: Да, процесс его может услышать и даже ответить.
  • Что делает?: Даёт процессу шанс не сдохнуть как собака, а прибраться за собой: сохранить все данные, закрыть файлы, попрощаться с дочерними процессами — в общем, сделать всё красиво.
  • Цель: Уйти с достоинством, не насрав в штаны и не потеряв ничего важного.

SIGKILL (Сигнал 9, kill -9) — это уже пиздец.

  • Суть: "Всё, пидор, кончилось". Прилетает в окно с бульдозером.
  • Можно ли его послать?: Нет, сука, его невозможно перехватить или проигнорировать. Это приказ ядра, и он железный.
  • Что делает?: Операционка сразу, без предупреждения, вырубает процесс нахуй. Никакой очистки, никаких "ой, секундочку". Просто — хлоп, и нету.
  • Цель: Гарантированно прибить процесс, когда он уже совсем охренел и не реагирует ни на что.

Короче, главная разница — в возможности сказать последнее "прощай". SIGTERM — это "дай пять секунд, я сохранюсь", а SIGKILL — это "молчи и умри".

Вот, смотри, как можно SIGTERM поймать в Питоне и не опозориться:

import signal
import sys
import time

def handle_sigterm(signum, frame):
    print(f"[{time.time():.2f}] Получен SIGTERM ({signum}). Начинаю корректное завершение...")
    # Тут можно всё прибрать: закрыть базу, отписаться куда надо, сохранить кэш.
    time.sleep(1) # Притворяюсь, что прибираюсь
    print(f"[{time.time():.2f}] Очистка завершена. Выход.")
    sys.exit(0)

# Вешаем наш хитрый обработчик на SIGTERM
signal.signal(signal.SIGTERM, handle_sigterm)

print(f"[{time.time():.2f}] Процесс запущен. Ожидаю сигналы...")
try:
    while True:
        time.sleep(5) # Делаю вид, что работаю
except KeyboardInterrupt:
    print(f"[{time.time():.2f}] Получен KeyboardInterrupt (Ctrl+C), выход.")
    sys.exit(0)

Если этому скрипту послать kill <PID> (SIGTERM), он вежливо попрощается и выйдет. А если вломиться с kill -9 <PID>, то он просто исчезнет, как будто его и не было, даже не пискнув. Ёперный театр!

Так как же жить? Правило простое, блядь: сначала всегда SIGTERM. Дай процессу пару секунд на сборы. Если он затупил и не реагирует — вот тогда уже, с чистой совестью, добивай SIGKILL. Так и система целее будет, и данные не потеряются. А то сразу с девяткой лезть — это как гаечным ключом чинить часы, овердохуища вреда можно нанести.