В системах POSIXy (Linux, Mac, BSD) существует довольно простой, но умный способ для процесса обслуживания достичь этого. Для этого даже не нужны никакие привилегии.
Основная идея очень проста: когда служба знает, что перезапустится, она создаст отдельный дочерний процесс (в новом сеансе и группе процессов, поэтому он будет переименован в init), содержащий прослушивающий сокет (ы) , Тогда родитель просто больше не будет accept()
новых подключений, завершит все неполные ответы и повторно выполнит себя с обновленным двоичным файлом.
Процесс-держатель также будет прослушивать входящие соединения через сокет домена Unix (потоковый или seqpacket; ориентированный на соединение). Обновленный экземпляр сервера будет подключаться к процессу держателя со вспомогательной полезной нагрузкой SCM_CREDENTIALS, которая включает проверенного в ядре пользователя и группу, под которой запускается процесс, и идентификатор процесса, который процесс держателя может использовать, чтобы проверить, является ли подключающаяся сторона обновленной версией двоичного файла. (В Linux это можно сделать путем сравнения stat()
из /proc/PID/exe
и ожидаемого исполняемого файла.) Если другой конец авторизован, держатель передает дескрипторы прослушивающего сокета обратно, используя вспомогательную полезную нагрузку SCM_RIGHTS. Наконец, обновленный сервис отправляет последнюю благодарность, которая сообщает завершающемуся процессу держателя (который также закрывает свои копии дескрипторов слушающих сокетов).
Пока достаточно невыполненных заданий (см. listen()
) (или syncookies , включенных в Linux, что делает это задание практически неограниченным), это должен быть достаточно надежный подход.
При желании я могу привести пример кода о том, как это будет работать в Linux. (Я считаю, что здесь важны аспекты безопасности, поэтому я определенно хотел бы заняться вещами только для Linux, такими как проверка /proc/PID/exe
, чтобы убедиться, что только обновленный двоичный файл может повторно получить сокеты прослушивания.)