Как выполнить мягкое (graceful) завершение процесса в Linux?

«Как выполнить мягкое (graceful) завершение процесса в Linux?» — вопрос из категории Linux, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Мягкое завершение — это отправка сигнала, который процесс может перехватить и корректно обработать (закрыть файлы, завершить транзакции, сохранить состояние). Основной сигнал для этого — SIGTERM (сигнал 15).

Стандартная последовательность действий:

  1. Найти PID процесса:

    ps aux | grep -i <process_name>
    # Или с помощью pgrep
    pgrep -f <process_name>
  2. Отправить SIGTERM:

    kill -15 <PID>
    # Или по имени
    pkill -15 -f <process_name>

    После этого у процесса есть время на завершение (обычно это 30 секунд, но зависит от приложения).

  3. Если SIGTERM не сработал — SIGINT (2): Это сигнал, аналогичный нажатию Ctrl+C в терминале.

    kill -2 <PID>
  4. Только в крайнем случае — SIGKILL (9): Сигнал SIGKILL нельзя перехватить или проигнорировать. Я использую его, только если процесс не реагирует на мягкие сигналы, понимая риски (потеря данных, неконсистентное состояние).

    kill -9 <PID>

Практический пример для веб-сервера (Nginx):

# Graceful shutdown Nginx (завершит обработку текущих соединений)
sudo nginx -s quit
# Эта команда внутри отправляет SIGQUIT мастер-процессу

# Альтернативно, если знаем PID мастера:
sudo kill -QUIT $(cat /var/run/nginx.pid)

Важно для скриптов: В bash-скриптах, которые запускают долгоживущие процессы, я использую trap для обработки сигналов завершения и очистки.

#!/bin/bash
cleanup() {
  echo "Получен сигнал завершения, останавливаем дочерние процессы..."
  kill -TERM $child_pid 2>/dev/null
}
trap cleanup TERM INT

# Запуск основного процесса в фоне
./my_long_running_process &
child_pid=$!

# Ожидание завершения
wait $child_pid