systemd: PID file /var/run/nginx.pid not readable (yet?) after start.

Gena Makhomed gmm на csdoc.com
Пт Ноя 24 11:30:41 UTC 2017


On 24.11.2017 6:12, Maxim Dounin wrote:

>>> Но сама идея, что все должны сесть и заняться выпиливанием
>>> стандартного паттерна, который работал десятки лет, и делать
>>> вместо это что-то своё с синхронизацией - не взлетит.

>> Эта идея уже взлетела. Если демон состоит из одного процесса
>> - systemd может однозначно узнать его pid, проблемы могут возникать
>> только с теми демонами, которые состоят из нескольких процессов.
>> Из известных мне сервисов состоящих из более чем одного процесса:

>> * postfix - сделали синхронизацию и проблем с systemd больше нет.
>> * httpd - перевели на Type=notify и проблем с systemd больше нет.
>> * php-fpm - перевели на Type=notify и проблем с systemd больше нет.
>> * nginx - только с этим сервисом наблюдаются проблемы под systemd.

> Давайте, всё-таки, опеределимся: мы за всё хорошее против всего
> плохого (== чтобы демоны писали pid-файлы до выхода запущенного
> процесса, потому что по другому - плохо), или вопрос исключительно
> в том, чтобы systemd не ругался в логи?

Так ведь systemd и ругается в логи потому что по другому - плохо.
Например, команда "/etc/init.d/nginx start ; /etc/init.d/nginx stop"
будет глючить на системах, где nginx запускается в виде SysV сервиса.

> Если за всё хорошее - то проблема, очевидно, не ограничевается
> сервисами из более чем одного процесса, и не решается переводом на
> Type=notify.  Она вообще ортогональна существованию systemd.  И
> идея её решения, очевидно, не взлетела, и уже наверное не взлетит.

В MacOS X есть launchd - там сервисам вообще запрещено делать fork()
и вызывать функцию daemon() - и ничего, никто еще умер, все работает.
https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html

systemd - это такой же launchd, но для системы Linux. Только для своих
конфигурационных файлов он использует ini синтаксис вместо формата xml
и небезуспешно пытается быть обратно совместимым со старыми SysV Daemons

Но свои специфичные требования к сервисам есть и у systemd:
https://www.freedesktop.org/software/systemd/man/daemon.html

15. Call exit() in the original process. The process that invoked
the daemon must be able to rely on that this exit() happens
after initialization is complete and all external communication
channels are established and accessible.

Одним из таких communication channels как раз и является pid-файл.

> Если чтобы systemd не ругался - то проблема, очевидно, не в том,
> чтобы сделать хорошо, а в том, убрать конкретную ругань (которая
> не несёт практического смысла, см. ниже).  И предолженный ранее
> workaround про sleep 0.1 - вполне себе в этом ключе же решение?

sleep 0.1 - это race condition на ровном месте, плохой workaround.
Лучше будет если такого workaround`а в unit-файлах nginx не делать.

Когда команда "/etc/init.d/nginx start ; /etc/init.d/nginx stop"
глючит - это ведь отрицательно сказывается на репутации nginx.
И эта проблема вообще ортогональна существованию systemd.

>> systemd однозначно определяет pid демонов состоящих из одного процесса
>> и поэтому для них в юнит-файле можно вообще не указывать опцию PIDFile=
>> - все будет работать как надо даже если они стартуют без синхронизации.
>>
>> Вот что говорит Lennart Poettering из Red Hat:
>>
>> If you use Type=forking, then you'll get away with not specifiying a
>> PID file in most cases, but it's racy as soon as you have more than
>> one daemon process, and nginx appears to be one of this kind, hence
>> please specify PIDFile=.
>>
>> https://lists.freedesktop.org/archives/systemd-devel/2017-November/039833.html
> 
> Ну вот я посмотрел на это место чуть подробнее, и имею сказать,
> что это не совсем соответствует действительности.  Единственное,
> для чего нужен PIDFile в случае nginx'а - это чтобы systemd
> нормально реагировал на binary upgrade.
> 
> Для правильного детектирования основного процесса при запуске
> PIDFile не нужен, так как master-процесс - единственный, у кого
> parent'ом systemd, у остальных процессов parent'ом будет master.
> И соответственно все остальные процессы успешно отфильтрует вот
> этот код,
> https://github.com/systemd/systemd/blob/master/src/core/cgroup.c#L1727:
> 
>                  /* Ignore processes that aren't our kids */
>                  if (get_process_ppid(npid, &ppid) >= 0 && ppid != mypid)
>                          continue;
> 
> Однако если PIDFile не указывать, то "service nginx upgrade"
> приведёт к тому, что после выхода старого мастера systemd будет
> считать, что nginx умер, и убьёт все новые процессы.  Поэтому
> PIDFile указывать таки надо.
> 
> Соответственно имеем то что имеем: PIDFile указывать надо, от
> этого на старте могут появляться сообщения про "PID file not ... yet?".
> Сообщения эти безвредные, и ни на что не влияют, кроме собственно
> появления самих сообщений.
> 
> Если идти по пути синхронизации через pipe, то патч получается
> как-то такой.  Не могу сказать, что он мне нравится, особенно в
> контексте решения задачи "чтобы у systemd в логе стало на одну
> строчку меньше".

Есть проблема "/etc/init.d/nginx start ; /etc/init.d/nginx stop"
на старых системах, использующих SysV систему инициализации.

И есть еще проблема не полной совместимости nginx с требованиями,
которые systemd предъявляет к SysV Daemons - это имиджевая проблема.

Сообщение "PID file not ... yet?" - это только следствие этих проблем.

-- 
Best regards,
  Gena



Подробная информация о списке рассылки nginx-ru