Перехоплення користувальницьких сигналів в go

Перехоплення користувальницьких сигналів в Go

Сигнали являють собою обмежений спосіб комунікації між процесами. Сигнали використовують для переривання виконання програми і спрацьовування певного обробника. Наприклад, коли ви натискаєте комбінацію клавіш CTRL + C в терміналі для зупинки запущеної програми, то таким чином ви посилаєте сигнал SIGINT. Зазвичай, при отриманні сигналу SIGINT процес побивається, але деякі процеси можуть перехоплювати сигнал і ігнорувати його чи виконувати деяку підготовчу роботу перед виходом. Ще один досить відомий сигнал SIGKILL набагато "брутальне". Як тільки процес отримує цей сигнал, то відразу ж припиняє свою роботу і немає ніяких способів ігнорувати цей сигнал. Існує дуже багато різних сигналів, їх опис можна знайти на wikipedia.

Посилати сигнали процесу можна за допомогою команди kill . Тут PID - це ідентифікатор процесу. Наприклад, щоб завершити певний процес, ви можете надіслати сигнал SIGKILL скориставшись командою kill -KILL . Для зручності можна використовувати команду pkill і замість ідентифікатора вказувати ім'я процесу.

У цьому пості ми будемо говорити про спеціальні призначених для користувача сигналах USR1 і USR2. Обидва ці сигналу надаються цілком в ваше розпорядження і ви самі можете визначити їх обробники. Я покажу кілька популярних способів їх використання. Всі приклади написання мовою Go, але основні ідеї не залежать від вибраної мови і можуть бути реалізовані на чому завгодно.

перехоплювання сигналів

У Go ви можете перехоплювати сигнали з використанням функції signal.Notify (chan os.Signal, syscall.Signal). Ця функція приймає канал і повідомляє вам, коли стався перехвать сигналу. Коли програма отримує сигнал, то в канал посилається значення типу os.Signal. Приблизно це виглядає так:

Тепер ми знаємо як перехоплювати сигнали і визначати наші власні обробники.

Перемикач для режиму логування.

Давайте уявимо, що у вас є веб-додаток, яке, звичайно ж, пише логи. Зробити лог дуже повним і багатослівним вважається не дуже хорошою ідеєю, тому що лог-файли розростуться моментально. Саме тому придумали різні рівні логування (INFO, DEBUG, WARN, і т.д.). Ви запускаєте свій додаток із зазначенням рівня, але якщо ви захочете отдебажіть яку ні будь проблему, то вам потрібно буде перезавантажити ваш додаток із зазначенням іншого рівня логування.

Для простоти припустимо, що у вас є тільки для два рівня логування (безшумний і багатослівний). Код нижче перемикає рівні логування як тільки процес отримує сигнал USR1.

Нагадаю, що для відправки сигналу потрібно виконати команду:

У цьому прикладі бінарник з програмою називається signals.

Читання конфігураційних файлів.

Ще один зручний варіант використання сигналів, це перевантаження конфігураційних файлів без перезапуску програми. Уявімо, що у вас є додаток, яке Новомосковскет конфігурацію з YAML файлу і просто виводить значення конфігурації на екран. Трохи модифікувавши це додаток, ми можемо змінити стару конфігурацію на нову просто відправивши необхідний сигнал.

висновок