Привет. Сегодня про сигналы и как с ними взаимодействовать через bash скрипты. Да те самые SIGINT, SIGTERM, SIGKILL.
Вероятно ты про них слышал. Ладно, скажу больше, ты даже ими пользуешься. Банально нажимая CTRL+C, ты посылаешь сигнал SIGINT. Этот сигнал позволяет скрипту корректно завершить работу.
Если прервать скрипт по нажатию CTRL+C, то вернется код ошибки 130 (
echo $?). А откуда взялось 130? Потому что если процесс завершается из-за полученного сигнала, он возвращает значение, которое является суммой 128 и кода сигнала. SIGINT = 2, итого получаем 128+2=130.
Цифра 128 выбрана не случайно, сделано это для того, чтобы избежать конфликтов с другими возвращаемыми значениями процесса. Linux использует значения от 0-127 для обозначения различных ошибок и успешного завершения процесса. Поэтому значения от 128 и выше можно использовать для обозначения сигналов, приведших к завершению процесса, не создавая путаницы с кодами завершения процесса.
Для обработки сигналов, в 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.Таким образом в хендлерах мы можем построить любую логику, например вывести слово «хуй». А если выпилить
exit 1, то по нажатию CTRL+C скрипт вообще никак не отреагирует на завершение и продолжит выполняться дальше. БЕСКОНЕЧНО!Прям море возможностей открывается. В малварях частенько такой подход используют, именно с перехватом и подавлением сигналов. Но это не наша тема, просто для информации.
SIGTERM
= Этот сигнал обычно отправляется операционной системой при попытке завершения процесса. Обработка SIGTERM позволяет скрипту завершить работу безопасно и корректно освободить ресурсы.
Да, есть еще SIGKILL, а вот его обработать не получится. Он нужен для крайних мер. Например, если из скрипта выше убрать
exit 1, то бесконечный цикл удастся завершить только через SIGKILL (kill PID). Ну ту тоже логично, всё продумано.Но я уверен, что и SIGKILL можно перехватить, правда пока лень с этим разбираться, всяко придется в ядро лезть в strace ковыряться и возможно что-то патчить.
Существуют и другие сигналы SIGHUP / SIGUSR1 / SIGPIPE / SIGCHLD и т.п. но сути это не меняет, пост про перехват сигналов.
Обработка сигналов, это как юнит тесты, они нужны, но никто их не пишет. Но в бест-практиках очень даже рекомендуется использовать такие обработки.
В принципе на этом можно и закончить, тему разобрали, база есть, дальше уже от своих потребностей двигайся и наращивай функционал. На собесах кстати иногда спрашивают про обработку сигналов и если на этот вопрос ответить, оффер твой.
Всех с пятницей, хороших предстоящих выходных и береги себя! Увидимся!
tags: #bash #linux
—
💩 @bashdays