Я реализую программу, которая работает 24/7. Он постоянно выполняет задачи каждые 15 секунд или около того, однако выполнение некоторых задач может занять произвольное время (более 15 секунд), и не рекомендуется выполнять другие операции над одним и тем же рабочим во время выполнения задачи (некоторые задачи требуют развертывание и удаление экземпляров виртуальных машин). Выполнение этого с помощью cronjob без сохранения состояния потребует сложной логики блокировок, которую трудно масштабировать, поэтому это не вариант.
Программа имеет сложное и тяжелое состояние, в основном это ядро или большой кластер, который занимается планированием заданий, проверкой состояния, перезапуском мертвых заданий и обновлением окончательных результатов, поэтому идея состоит в том, чтобы он всегда работал как ядро системы.
Прямо сейчас полное программное обеспечение реализовано как подкласс threading.Thread со всеми соображениями параллелизма, которые уже решены.
Конечная точка системы — это ОЧЕНЬ ПРОСТОЙ сценарий, который считывает конфигурации из аргументов и файлов и инициализирует ими потоковый класс. После этого он запускает метод start() и ждет вечно, перезапуская основной класс, если он каким-то образом дает сбой.
Что я хочу сделать, так это реализовать этот простой класс как хорошо себя зарекомендовавший демон-процесс (сейчас я использую nohup и & для достижения цели) с запуском/остановкой И простым методом состояния, который печатает информацию о запущенных заданиях, размере текущего кластера и т. д., весь простой текст . Прямо сейчас у меня есть прослушиватель сигналов, который эмулирует stop() и status(), изящно останавливая потоки (при необходимости) и выводя вывод в файл.
Удаленный кластер и его логика связи/расписания — это настраиваемая реализация с использованием Pyro4, поэтому одним из вариантов будет регистрация сам основной процесс в Pyro Daemon, поэтому одной из альтернатив может быть регистрация самого демонизируемого класса и использование некоторого пользовательского кода Python для подключения к нему и получения статуса, однако я думаю, что это излишне и полагается на демона pyro, который добавляет неизбежный сбой указывает на систему.
Я наткнулся на несколько библиотек, которые утверждают, что создают правильных демонов:
Эти классы выглядят надежными и достаточно простыми, чтобы соответствовать моим текущим потребностям (я еще не понял, как сделать часть status(), однако это должно быть легко). Есть ли другая библиотека, которая делает это более надежным способом? прямо сейчас у меня нет времени проводить проверки стабильности библиотеки демонов, поэтому, даже если это может быть немного основано на мнении, я хотел бы узнать ваши мысли и практический опыт по этому поводу.
Все это о демонах linux, однако существует ли какой-нибудь ПРОСТОЙ класс, который обрабатывает службы Windows так же, как и демоны linux? Моя текущая программа предназначена только для Linux из-за других внешних ограничений, но в будущем было бы неплохо избежать программирования двух разных ветвей.
Для моего текущего проекта мне не нужно ничего, кроме представленного выше, однако, думая о будущем, я хотел бы иметь возможность ОТПРАВЛЯТЬ некоторую информацию ОТ терминала демонам. Ничего сложного, просто команды с простыми строковыми/числовыми данными в качестве аргументов.
Например, было бы неплохо иметь функцию «reload_config», которая позволяет мне передавать новое местоположение файла конфигурации из консоли. Прямо сейчас, чтобы перезагрузить конфигурацию, я изменяю ТЕКУЩИЙ файл конфигурации и говорю процессу прочитать его снова, используя сигнал. Это уменьшает возможные функции, которые могут быть реализованы с помощью этого (вы можете использовать временный файл в известном месте, чтобы сохранить команду и заставить клиента прочитать ее, но это также не чистое решение)
Насколько мне известно, единственными правильными способами добиться этого (помимо использования файла связи) являются:
- Сокет прослушивания TCP в потоке, который прослушивает команды, отправленные с помощью специального клиента. Это создает проблемы безопасности и вынуждает вас создавать некоторую грамматику, которая позволяет вам представлять ваши команды наиболее эффективным способом, а также добавляет проблемы с коммуникацией.
- Простой веб-сервер на Python, который действует как посредник с заказами: клиент публикует на веб-сервере, а поток получает оттуда. С безопасностью теперь легче справиться, чем в предыдущем случае (https избавляет от необходимости заботиться о шифровании и атаках «человек посередине»), но это все еще проблема.
- Использование Pyro4 для удаленной загрузки класса при необходимости с управляющих клиентов, что мне кажется слишком грязным.
- Использование «файла связи» для получения/отправки сложных данных в процесс. Это кажется грязным и совершенно не соответствует нынешнему уровню техники.
** ПРИМЕЧАНИЕ. В настоящее время я использую logging.Logger для прямого входа в файл, может ли это быть проблемой? Насколько я знаю (и предполагаю), это не так, но кто знает...
Кроме того, согласно этому первому ответу, "systemd делает много демоны устарели", я не очень привык к systemd (не хотел обновляться до современных ОС, пока не смог больше откладывать), однако этот метод я могу просто делать то, что я сейчас занимаюсь: ловлю и корректно обрабатываю сигналы закрытия и автозапуск/убийство скрипта из systemd, чего вроде бы не достаточно.
Хотя кажется, что если я не реализую более сложные клиент/серверы, я не смогу отправлять команды с аргументами своим службам, я ошибаюсь? Идеальной ситуацией было бы иметь возможность запускать такие команды:
systemctl custom_command python_service custom_argument
хотя я не думаю, что systemd поддерживает что-то подобное, я ошибаюсь?
В любом случае, для решения основных вопросов этих возможностей будет достаточно:
systemctl start python_service
systemctl stop python_service
systemctl restart python_service
systemctl reload python_service
systemctl status python_service