Время неумолимо. Кажется ещё сегодня пятница, а уже на горизонте маячит понедельник.

Привет. Сегодня про сигналы и как с ними взаимодействовать через bash скрипты. Да те самые SIGINT, SIGTERM, SIGKILL.

Вероятно ты про них слышал. Ладно, скажу больше, ты даже ими пользуешься. Банально нажимая CTRL+C, ты посылаешь сигнал SIGINT. Этот сигнал позволяет скрипту корректно завершить работу.

Если прервать скрипт по нажатию CTRL+C, то вернется код ошибки 130 (echo $?). А откуда взялось 130?

Потому что если процесс завершается из-за полученного сигнала, он возвращает значение, которое является суммой 128 и кода сигнала. SIGINT = 2, итого получаем 128+2=130.

Для обработки сигналов, в Bash можно использовать обработчики. Спасибо, капитан!

Пример обработки сигналов:

#!/bin/bash

# Функция для обработки SIGINT (Ctrl+C)
sigint_handler() {
    echo "Caught SIGINT (Ctrl+C). Exiting..."
    exit 1
}

# Функция для обработки SIGTERM
sigterm_handler() {
    echo "Caught SIGTERM. Exiting..."
    exit 1
}

# Установка обработчиков сигналов
trap sigint_handler SIGINT
trap sigterm_handler SIGTERM

# Главный цикл
while true; do
    echo "Script is running..."
    sleep 1
done

Скрипт запустит бесконечный цикл. Если нажать CTRL+C, сработает хендлер sigint_handler и скрипт завершится с кодом 1. Видишь, мы поменяли дефолтный код 130 на 1.

А хендлер sigterm_handler сработает в том случае если скрипт убить через kill -TERM PID. Процесс так же завершится с кодом 1.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Таким образом в хендлерах мы можем построить любую логику, например вывести слово «хуй». А если выпилить exit 1, то по нажатию CTRL+C скрипт вообще никак не отреагирует на завершение и продолжит выполняться дальше. БЕСКОНЕЧНО!

Прям море возможностей открывается. В малварях частенько такой подход используют, именно с перехватом и подавлением сигналов. Но это не наша тема, просто для информации.

Да, есть еще SIGKILL, а вот его обработать не получится. Он нужен для крайних мер. Например, если из скрипта выше убрать exit 1, то бесконечный цикл удастся завершить только через SIGKILL (kill PID). Ну тут тоже логично, всё продумано.

Но я уверен, что и SIGKILL можно перехватить, правда пока лень с этим разбираться, всяко придется в ядро лезть в strace ковыряться и возможно что-то патчить.

Существуют и другие сигналы SIGHUP / SIGUSR1 / SIGPIPE / SIGCHLD и т.п. но сути это не меняет, пост про перехват сигналов.

Обработка сигналов, это как юнит тесты, они нужны, но никто их не пишет. Но в бест-практиках очень даже рекомендуется использовать такие обработки.

В принципе на этом можно и закончить, тему разобрали, база есть, дальше уже от своих потребностей двигайся и наращивай функционал. На собесах кстати иногда спрашивают про обработку сигналов и если на этот вопрос ответить, оффер твой.

Всех с пятницей, хороших предстоящих выходных и береги себя! Увидимся!