Может ли другой процесс сигнализировать systemd о перезапуске сервиса?

Вопрос или проблема

У нас есть служба, которая управляется systemd. Я ищу способ программно перезапустить эту службу по запросу – например, отправив сигнал, записав в файл или отправив сообщение через сокет.

Контекст: служба, управляемая systemd, управляет пулом безголовых экземпляров Chrome. Но она делает это довольно плохо, и со временем количество экземпляров и использование памяти увеличиваются. systemctl restart решает эту проблему.

Я могу установить RuntimeMaxSec и Restart=always, чтобы периодически перезапускать прокси, но в момент перезапуска он может выполнять какие-то задачи.

Другой службой на этой машине является единственный потребитель прокси Chrome, который знает, когда не использует его. Таким образом, периодически, когда он не использует прокси Chrome (чтобы не потерять ни один запрос), он может перезапустить его.

Как я могу это сделать?

Одно из решений – заставить другую службу фактически выполнить systemctl restart some_service. Это требует sudo, но можно использовать файл sudoers (visudo), чтобы дать пользователю разрешение выполнить одну конкретную команду: some-user ALL=NOPASSWD: /some/command some args

Если вы хотите избежать использования sudo, вы можете установить флаг длительности для вашего пользователя и создать пользовательскую службу вместо системной службы. Это может не работать на CentOS 7 и ниже.

Еще одно решение – спросить systemctl, какой PID

systemctl --user status your_scraper

затем отправить SIGHUP этому идентификатору процесса

os.kill(main_pid_of_your_scraper, signals.SIGHUP)

что вам нужно поймать внутри вашего приложения и сбросить ваш браузер.

signal.signal(signal.SIGHUP, restart_myself)

Это также хорошо взаимодействует с systemctl, поскольку systemctl reload также отправляет сигнал SIGHUP этому процессу.

Разрешено ли потребительской службе перезапускаться? Если да, то вы можете перезапустить потребителя и определить proxy.service для автоматического перезапуска, если потребитель перезапускается.

proxy.service должен включать

[Unit]
BindsTo = consumer.service
Requires = consumer.service
After = consumer.service

Затем, когда потребитель простаивает, завершите его программно с конкретным кодом выхода, например, 42. И определите consumer.service для перезапуска при коде выхода 42.

Ответ или решение

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

Основные методы перезапуска службы

  1. Использование команд systemctl с привилегиями sudo
    Одним из самых простых решений является использование команды systemctl restart. Однако для выполнения этой команды требуется привилегия суперпользователя. Это можно обойти, настроив файл sudoers с помощью visudo, чтобы разрешить конкретному пользователю выполнять команду без запроса пароля. Например:

    some-user ALL=NOPASSWD: /bin/systemctl restart your_service
  2. Создание пользовательской службы с поддержкой linger
    Если минимизация привилегий важна, можно рассмотреть создание службы на уровне пользователя (user service) вместо системной. Для этого требуется, чтобы пользователь имел установленный флаг linger (это позволяет службам работать вне сеанса пользователя). Создание пользовательской службы обычно работает без дополнительных привилегий, но может не поддерживаться в более старых дистрибутивах, таких как CentOS 7 или ниже.

  3. Посылка сигналов процессам
    Еще одним подходом является отправка сигналов напрямую процессу. Сначала вы можете получить идентификатор процесса (PID) вашей службы с помощью команды:

    systemctl status your_service

    Затем можно использовать библиотеку Python для отправки сигнала SIGHUP этому PID. Например:

    import os
    import signal
    
    os.kill(main_pid_of_your_service, signal.SIGHUP)

    Ваша служба должна обрабатывать этот сигнал, чтобы выполнить перезапуск экземпляров. Рекомендуется использовать обработчик сигналов для корректного реагирования на SIGHUP.

    import signal
    
    def restart_myself(signum, frame):
       # Логика перезапуска вашего браузера или экземпляра
       pass
    
    signal.signal(signal.SIGHUP, restart_myself)

    Данный метод совместим с systemctl reload, который также отправляет SIGHUP.

  4. Использование зависимости между службами
    Если ваша служба-потребитель может перезапускаться, вы можете установить зависимость между службами в конфигурационном файле вашего proxy-сервиса. Это можно сделать, добавив в файл сервиса следующие строки:

    [Unit]
    BindsTo=consumer.service
    Requires=consumer.service
    After=consumer.service

    Затем, когда потребитель будет в неактивном состоянии, вы можете завершить его работу с конкретным кодом завершения (например, 42). Конфигурация вашего consumer.service может быть настроена так, чтобы перезапускаться только при выходе с кодом 42.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...