SystemdDoctor
nginx.service веб-серверчастое

nginx.service в systemd: разбор отказов запуска

У nginx почти все отказы запуска ловятся до старта самого сервера: unit-файл вызывает nginx -t предварительной командой, и падение происходит на ней. Поэтому первая строка разбора — вывод проверки конфигурации, а не журнал службы.

О службе

В дистрибутивных unit-файлах nginx запускается с Type=forking и предварительной командой ExecStartPre=/usr/sbin/nginx -t. Такая проверка удобна: она отсекает ошибки в конфигурации до того, как старый процесс будет остановлен. Но она же меняет картину в журнале: код возврата приходит от проверки, и в статусе видна строка Control process exited, а не Main process.

Вторая особенность — работа с правами. Главный процесс nginx работает от root, чтобы занять порты 80 и 443, а рабочие процессы переходят на непривилегированного пользователя из директивы user в nginx.conf. Из-за этого ошибки доступа к файлам приходят от рабочих процессов, а не от службы: в журнале это строки с уровнем crit и alert, которые к самому systemd отношения не имеют.

Третья — перезагрузка настроек. systemctl reload nginx посылает сигнал HUP, и nginx поднимает новые рабочие процессы, не разрывая текущие соединения. Полный перезапуск (restart) обрывает соединения, поэтому для правки конфигурации почти всегда нужен именно reload. Если reload не применяет изменения, проверьте, что правили тот файл, который действительно включён.

Как устроена

Тип unitобычно Type=forking с PIDFile=/run/nginx.pid
Проверка конфигурацииnginx -t — она же стоит в ExecStartPre= и её код вы видите при отказе
Перезагрузка настроекsystemctl reload nginx — сигнал HUP, соединения не рвутся
Пользователь рабочих процессовзадаётся директивой user в nginx.conf, а не User= в unit-файле
Куда пишет ошибкив error_log из nginx.conf; в журнал systemd попадает только то, что вышло до открытия файлов логов

Частые ошибки

53 записи базы отмечены за этой службой.

Сообщения журнала

Коды выхода

  • status=1/FAILURE в systemdКод 1/FAILURE означает, что программа запустилась и сама завершилась с ошибкой. Как найти настоящую причину в журнале службы.
  • status=0/SUCCESS, но служба считается упавшейПрограмма завершилась успешно, а systemctl показывает inactive или failed. Разбор: Type=simple против forking, RemainAfterExit, демонизация.
  • status=203/EXEC в systemdКод 203/EXEC означает, что systemd не смог выполнить программу из ExecStart=. Разбор причин: путь, права, интерпретатор, синтаксис оболочки.
  • status=205/LIMITS в systemdКод 205/LIMITS: systemd не смог применить ограничения ресурсов из Limit*=. Обычно значение недопустимо или превышает жёсткий предел.
  • status=217/USER в systemdКод 217/USER означает, что systemd не смог определить или сменить пользователя из User=. Разбор причин: пользователя нет, имя недопустимо, конфликт с DynamicUser.
  • status=218/CAPABILITIES в systemdКод 218/CAPABILITIES: не удалось применить набор возможностей процесса из CapabilityBoundingSet= или AmbientCapabilities=.
  • status=226/NAMESPACE в systemdКод 226/NAMESPACE: не удалось настроить пространства имён монтирования, UTS или IPC. Частая причина — путь в ReadOnlyPaths= или ProtectHome=.
  • status=240/LOGS_DIRECTORY в systemdКод 240/LOGS_DIRECTORY: не удалось подготовить каталог журналов службы в /var/log из LogsDirectory=.
  • status=4/NOPERMISSION в systemdКод 4/NOPERMISSION: программа сообщила о недостатке прав. По соглашению LSB это «у пользователя недостаточно привилегий».

Ресурсы и ограничения

  • Too many open files в журнале службыСлужба исчерпала лимит файловых дескрипторов. Как правильно поднять LimitNOFILE и когда дело в утечке.
  • kernel: TCP: request_sock … overflowСоединения теряются при наплыве: переполнена очередь ожидающих соединений. Как считать somaxconn и backlog.
  • nf_conntrack: table full, dropping packetСоединения обрываются под нагрузкой: заполнена таблица отслеживания соединений ядра.

Состояния результата

Конфигурация unit

Сигналы

  • signal=HUP (status=1/HUP) в systemdПроцесс службы завершён сигналом HUP. Обычно это перезагрузка настроек, которую программа поняла как команду выйти.
  • signal=INT и signal=QUIT в systemdПроцесс службы завершён сигналом INT или QUIT. Кто их посылает службам и почему это обычно не systemd.
  • signal=SEGV (status=11/SEGV) в systemdПроцесс службы завершён сигналом SEGV: обращение к недопустимой памяти. Как собрать дамп и что смотреть.
  • signal=TERM (status=15/TERM) в systemdПроцесс службы завершён сигналом TERM. Когда это нормальная остановка, а когда признак проблемы.

Ошибки служб

Коды выхода этой службы

Числа в status=N ниже 200 назначает сама программа, 200 и выше — systemd, когда не смог подготовить запуск.

statusЧто означает у этой службыКуда смотреть
1/FAILURE самый частый: проверка конфигурации не прошла или порт занят. Точную причину даёт строка nginx: [emerg] ... выше. разбор
203/EXEC путь к nginx в unit-файле неверен — бывает после ручной сборки в /usr/local. разбор
0/SUCCESS при inactive nginx ушёл в фон при Type=simple: нужен либо forking, либо daemon off. разбор

Диагностика

Проверка конфигурации с указанием файла и строки. При отказе запуска начинать надо с неё.

sudo nginx -t

Показывает, упала предварительная проверка или главный процесс.

systemctl status nginx --no-pager -l

Сообщения nginx, которые не успели попасть в его собственный файл ошибок.

journalctl -u nginx -n 50 --no-pager

Кто занимает веб-порты: вторая по частоте причина после ошибки в конфигурации.

sudo ss -tlnp | grep -E ":(80|443)\s"

Печатает итоговую конфигурацию со всеми включёнными файлами: видно повторные объявления адресов.

sudo nginx -T | grep -n "listen\|server_name" | head -20

Параметры unit, которые тут важны

  • Type=forking для обычной сборки, simple при `daemon off`
  • PIDFile=обязателен при forking, иначе systemd следит не за тем процессом
  • ExecReload=перезагрузка настроек сигналом HUP без разрыва соединений
  • LimitNOFILE=под нагрузкой значение по умолчанию быстро исчерпывается
  • ExecStartPre=проверка конфигурации до запуска — именно её код вы видите при отказе

Частые вопросы

Почему systemctl status показывает «Control process exited», а не ошибку nginx?

Потому что упала предварительная команда проверки конфигурации. Она выполняется до главного процесса, и её код становится кодом службы. Читайте строки nginx выше — там причина с номером файла и строки.

Изменил конфигурацию, сделал reload — ничего не изменилось. Почему?

Скорее всего правка в файле, который не включён в конфигурацию. Команда nginx -T печатает итоговый вариант со всеми include: если вашей правки там нет, файл не подключён.

Источники