Как передавать события сигналами реального времени в Bash

Не одевай 3.14зду в лапти, она и так смешная.

 читать первым в телеграм    читать первым в макс

Так-с, давай покончим с сигналами реального времени (СРВ) и выйдем на новый уровень написания Bash-скриптов, мы ж с тобой уже взрослые.

Вчера мы выяснили: СРВ имеют условный индекс 34–64 (в разных дистрибутивах может быть по-разному, проверяй).

Где их применять?

Давай глянем на примере. Сишкой задрачивать не буду, перепишем на Bash.

Задача: у меня есть серверный процесс, который должен получить уведомление от клиента с некоторыми данными (например, номер задачи).

Вместо передачи данных через файлы или другие средства нужно использовать сигналы реального времени.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Сначала будет нихуя непонятно, но под конец я тебе всё разжую. Не переживай, тут всё просто. Поймёшь суть, сможешь реализовать на любом языке программирования.

Пишем сервер signal_listener.sh

#!/bin/bash

handle_signal() {
    echo "Получен сигнал $1"
    echo "Переданные данные: $2"
}

trap 'handle_signal SIGRTMIN+0 "Task 1 выполнена"' RTMIN+0
trap 'handle_signal SIGRTMIN+1 "Task 2 выполнена"' RTMIN+1

echo "Слушатель запущен. PID: $$"
echo "Ожидаем сигналы..."

while true; do
    sleep 1
done

Пишем клиент signal_sender.sh

#!/bin/bash

if [ $# -ne 2 ]; then
    echo "Использование: $0 <PID> <TASK>"
    echo "TASK может быть 1 или 2"
    exit 1
fi

PID=$1
TASK=$2

if [ "$TASK" -eq 1 ]; then
    kill -RTMIN+0 $PID
    echo "Отправлен сигнал SIGRTMIN+0 (Task 1) процессу с PID $PID"
elif [ "$TASK" -eq 2 ]; then
    kill -RTMIN+1 $PID
    echo "Отправлен сигнал SIGRTMIN+1 (Task 2) процессу с PID $PID"
else
    echo "Ошибка: TASK должен быть 1 или 2"
    exit 1
fi

trap = перехватываем сигналы, для СРВ пишем: RTMIN+0 и RTMIN+1.

kill -RTMIN+N = отправляет СРВ. Номер сигнала (например, RTMIN+0) задаёт, какой именно сигнал будет обработан.

chmod +x signal_listener.sh signal_sender.sh

Запускаем первый скрипт, видим его PID:

Слушатель запущен. PID: 20821

Во втором терминале запускаем второй скрипт:

./signal_sender.sh 20821 1

Отправлен сигнал SIGRTMIN+0 (Task 1) процессу с PID 20821

Не забываем подставить PID, который выдал первый скрипт.

После отправки СРВ в терминале, где запускали первый скрипт, видим:

Получен сигнал SIGRTMIN+0
Переданные данные: Task 1 выполнена

Вот это нихуя себе! То есть signal_sender подключился к процессу 20821 и передал в него данные.

В нашем случае данные — это 1 или 2. А скрипт signal_listener успешно это схавал и переварил, исходя из логики.

Использование СРВ открывает ОГРОМНЫЕ возможности, чтобы несколько скриптов или приложений взаимодействовали друг с другом на низких уровнях, не используя велосипеды и прокладки.

А когда какой сигнал использовать?

Хе… 34–64… Если у тебя несложная логика, можешь использовать любой индекс в этом диапазоне. Но если логика совсем ебанутая, то логичнее использовать СРВ с разными индексами для передачи данных.

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

Типа такого:

SIGRTMIN+0 (34): "Начать обработку данных"
SIGRTMIN+1 (35): "Обновить конфигурацию"
SIGRTMIN+2 (36): "Выебать медведя в жопу"
SIGRTMIN+3 (37): "Остановить обработку данных"

Это избавляет от необходимости декодировать данные внутри обработчика, потому что обработка сразу зависит от типа сигнала.

А можно обрабатывать в порядке приоритета. СРВ обрабатываются в порядке их номеров (от SIGRTMIN к SIGRTMAX). Это заебись, если у тебя задачи с разным приоритетом.

SIGRTMIN+0: Высший приоритет (аварийная задача)
SIGRTMIN+1: Средний приоритет (регулярные уведомления)
SIGRTMIN+2: Низший приоритет (обновление статистики)

Если сигналы поступают одновременно, сначала обработается SIGRTMIN+0, потом SIGRTMIN+1 и т. д.

Если что-то ещё вспомню, накидаю отдельным постом.

Удачи тебе и береги себя!

Про сигналы писал ранее тут, тут, тут и тут.

Комментарии