В чем разница между сигналами SIGTERM (kill -15) и SIGKILL (kill -9) в Linux?

Ответ

Это два разных сигнала, используемых для завершения процессов в Unix-подобных системах, но они работают принципиально по-разному.

kill -15 (SIGTERM)

  • "Вежливый" запрос на завершение. Это сигнал по умолчанию для утилиты kill. Он сообщает процессу, что его просят завершиться.
  • Можно перехватить. Приложение может (и должно) перехватить этот сигнал, чтобы выполнить очистку: сохранить данные, закрыть файлы и сетевые соединения, завершить дочерние процессы.
  • Может быть проигнорирован. Процесс может проигнорировать SIGTERM, если он занят или некорректно написан.

kill -9 (SIGKILL)

  • Принудительное "убийство". Этот сигнал нельзя перехватить, заблокировать или проигнорировать.
  • Немедленное завершение. Ядро системы немедленно останавливает выполнение процесса, не давая ему шанса на очистку.
  • Опасность. Использование SIGKILL может привести к повреждению данных, оставленным "зомби"-процессам и утечкам ресурсов (например, временные файлы не будут удалены).

Пример перехвата SIGTERM в Go:

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)

func main() {
    // Создаем канал для получения сигналов ОС
    sigChan := make(chan os.Signal, 1)
    // Уведомляем наш канал о поступлении SIGINT или SIGTERM
    signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

    fmt.Println("Процесс запущен (PID: ", os.Getpid(), "). Ожидание сигнала...")

    // Блокируемся, пока не получим сигнал
    sig := <-sigChan
    fmt.Printf("nПолучен сигнал: %s. Начинаю корректное завершение...n", sig)

    // Здесь происходит логика очистки
    fmt.Println("Закрываю соединения, сохраняю состояние...")
    time.Sleep(2 * time.Second)

    fmt.Println("Работа завершена.")
}

Итог: Всегда следует сначала отправлять SIGTERM и давать процессу время на завершение. SIGKILL — это крайняя мера, которую стоит применять, только если процесс не отвечает на SIGTERM.