← Назад к вопросам

Зачем нужны сигналы в Linux?

2.0 Middle🔥 161 комментариев
#Linux и администрирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Сигналы в Linux: назначение и роль

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

Основное назначение сигналов

Сигналы решают проблему асинхронности:

  • Процесс может быть прерван в любой момент
  • ОС уведомляет процесс о событиях (сигнал от клавиатуры, таймер истёк, дочерний процесс завершился)
  • Процесс может определить свой обработчик сигнала (signal handler)

Основные применения сигналов

1. Управление процессом

# SIGTERM — корректное завершение
kill -TERM <pid>

# SIGKILL — насильственное завершение (нельзя перехватить)
kill -KILL <pid>

# SIGSTOP/SIGCONT — приостановка и возобновление
kill -STOP <pid>
kill -CONT <pid>

2. Обработка ошибок и исключений

# SIGSEGV — ошибка сегментации (доступ в неправильную память)
# SIGABRT — вызов abort()
# SIGFPE — ошибка вычислений (деление на 0)
# SIGILL — некорректная инструкция

3. Работа с вводом-выводом

# SIGINT — Ctrl+C (прерывание)
# SIGQUIT — Ctrl+\ (выход)
# SIGHUP — закрытие терминала

4. Таймеры и события

# SIGALRM — таймер (из alarm())
# SIGCHLD — дочерний процесс завершился
# SIGPIPE — запись в закрытый канал

Как процесс обрабатывает сигналы

На bash:

#!/bin/bash

# Определяем обработчик сигнала
trap 'echo "Получен сигнал SIGTERM, завершаю..."' TERM
trap 'echo "Получен сигнал SIGINT, отменяю операцию"' INT

echo "PID: $$"
echo "Ожидаю сигналы..."

while true; do
  sleep 1
done

На Python:

import signal
import time

def sigterm_handler(signum, frame):
    print("Получен SIGTERM, завершаю корректно...")
    exit(0)

def sigint_handler(signum, frame):
    print("\nПолучен SIGINT (Ctrl+C)")
    exit(1)

# Регистрируем обработчики
signal.signal(signal.SIGTERM, sigterm_handler)
signal.signal(signal.SIGINT, sigint_handler)

print(f"PID: {os.getpid()}")
while True:
    time.sleep(1)

Практические примеры в DevOps

Graceful shutdown в Docker:

FROM python:3.9
WORKDIR /app
COPY app.py .
CMD ["python", "app.py"]
# app.py
import signal
import sys

def graceful_shutdown(signum, frame):
    print("Shutdown signal received, cleaning up...")
    # Закрываем DB connections, flush logs
    sys.exit(0)

signal.signal(signal.SIGTERM, graceful_shutdown)

Перезагрузка конфига (Nginx):

# nginx перечитывает конфиг без перезагрузки
nginx -s reload  # отправляет SIGHUP процессу

Мониторинг дочерних процессов:

while true; do
    child_process &
    pid=$!
    
    # Перехватываем SIGCHLD (дочерний завершился)
    trap 'wait $pid; echo "Child exited with code $?"' SIGCHLD
    
    wait $pid
done

Типичные сигналы и их коды

СигналКодЗначениеПерехватывается
SIGTERM15ЗавершениеДа
SIGKILL9Убить процессНет
SIGINT2Ctrl+CДа
SIGSTOP19ПриостановитьНет
SIGCONT18ПродолжитьДа
SIGCHLD17Дочерний завершилсяДа
SIGHUP1Закрытие терминалаДа
SIGUSR1/210/12ПользовательскиеДа

Почему это важно для DevOps

  • Graceful shutdown: Даём приложению время на очистку ресурсов
  • Zero-downtime deployment: Перенаправляем запросы, затем корректно завершаем старый процесс
  • Управление ресурсами: Приостанавливаем и возобновляем процессы
  • Мониторинг: Отслеживаем состояние дочерних процессов
  • Конфигурация: Перезагружаем конфиг без перезагрузки (SIGHUP)