postfix.service в systemd: разбор отказов
В Debian и Ubuntu postfix.service не запускает почту: это пустышка с Type=oneshot и ExecStart=/bin/true. Настоящая работа идёт в экземпляре шаблона postfix@-.service, который подключает генератор systemd. Поэтому состояние active (exited) у postfix.service не говорит о почте ничего, и разбор любого отказа начинается не с него.
О службе
Устройство сбивает с толку сильнее, чем у любой другой службы из этого каталога. postfix.service в дистрибутивах Debian и Ubuntu объявлен как Type=oneshot с RemainAfterExit=yes и командой запуска /bin/true — он честно ничего не делает. Его роль в том, чтобы быть точкой, за которую тянутся настоящие службы: генератор postfix-instance-generator при каждой загрузке и при каждой перечитке описаний создаёт в каталоге postfix.service.wants ссылку postfix@-.service, а при нескольких экземплярах — по ссылке на каждый. Сам экземпляр объявлен в шаблоне postfix@.service как Type=forking с GuessMainPID=no, и запускает он не демон напрямую, а postmulti -i - -p start.
Отсюда главное следствие для разбора: systemctl status postfix почти всегда показывает active (exited) — и показывал бы то же самое, будь почта мертва. Смотреть надо на экземпляр: systemctl status postfix@-. Там же видны настоящие коды выхода. Второе следствие: экземпляра нет в списке unit-файлов, потому что он не включён обычным образом, а создан генератором на время работы системы. Проверять его наличие нужно либо по зависимостям пустышки, либо прямо в каталоге сгенерированных описаний.
Третья особенность — окружение самих процессов. Большинство служб postfix работает в изолированном корне /var/spool/postfix, и внутри у них нет ни системного файла разрешения имён, ни базы пользователей. Копию файла разрешения имён туда переносит отдельная пара unit: postfix-resolvconf.path следит за изменениями /etc/resolv.conf и запускает postfix-resolvconf.service. Если копия внутри изолированного корня устарела или её нет, письма начинают откладываться с жалобой на ненайденный узел — при полностью исправном разрешении имён в самой системе.
И последнее, о чём стоит знать заранее: в описании пустышки объявлен конфликт с sendmail.service и exim4.service. Установка postfix останавливает прежнюю почтовую службу, а обратная установка остановит postfix. Плюс условие ConditionPathExists=/etc/postfix/main.cf: без файла настроек служба не падает, а пропускается — в журнале это выглядит как «условие не выполнено», а не как ошибка.
Как устроена
| Что запускает postfix.service | ничего: Type=oneshot, ExecStart=/bin/true, RemainAfterExit=yes |
|---|---|
| Где настоящая служба | postfix@-.service — экземпляр шаблона postfix@.service, Type=forking |
| Кто подключает экземпляр | генератор /usr/lib/systemd/system-generators/postfix-instance-generator |
| Команда запуска экземпляра | postmulti -i - -p start, перед ней configure-instance.sh |
| Перезагрузка настроек | systemctl reload postfix — расходится на экземпляры через ReloadPropagatedFrom= |
| Условие запуска | ConditionPathExists=/etc/postfix/main.cf: без файла unit пропускается, а не падает |
| Конфликты | с sendmail.service и exim4.service — прежняя почтовая служба будет остановлена |
| Изолированный корень | /var/spool/postfix; копию resolv.conf туда носит postfix-resolvconf.path |
| Куда пишет | через системный журнал с идентификаторами вида postfix/smtp, postfix/cleanup |
Частые ошибки
10 записей базы отмечены за этой службой.
Сообщения журнала
- Почта не отправляется: письма остаются в очередиУведомления от служб не доходят: очередь почты растёт, соединение с сервером не устанавливается.
- Temporary failure in name resolution в журнале службыСлужба не может разрешить имя: не готова сеть, нет сервера имён, мешает изоляция. Разбор при загрузке и в работе.
- Address already in use при запуске службыПорт или адрес уже занят: bind() failed (98: Address already in use). Как найти владельца порта и что делать с остатками прежнего процесса.
- Permission denied в журнале службыОтказ в доступе у службы systemd: права на файл, каталоги по пути, пользователь службы, параметры изоляции, SELinux и AppArmor.
Конфигурация unit
- Одноразовая задача: как не получить ложный сбойПравильная настройка Type=oneshot: RemainAfterExit, коды возврата, зависимости и вызов по таймеру.
- Служба active, но не работает: обёртки и oneshotПочему состояние active не означает работающую программу: oneshot с RemainAfterExit, обёртки, потерянный главный процесс.
- Шаблонный unit: экземпляр не запускаетсяСлужба вида имя@экземпляр не запускается: нет файла настроек экземпляра, неверное экранирование, не включён шаблон.
Ресурсы и ограничения
- No space left on device в журнале службыНет места на устройстве: разбор по свободным блокам, по inode, по журналу systemd и по удалённым, но открытым файлам.
Ошибки служб
- Почтовая служба пишет в аварийный журнал и не принимает письмаСлужба сообщает о невозможности писать журналы или создавать файлы очереди: права на каталоги нарушены.
- Фильтр почты недоступен почтовой службе: сокет и группыПочтовая служба не может обратиться к фильтру: сокет создан с правами, недоступными её пользователю.
Коды выхода этой службы
Числа в status=N ниже 200 назначает сама программа, 200 и выше — systemd, когда не смог подготовить запуск.
| status | Что означает у этой службы | Куда смотреть |
|---|---|---|
0/SUCCESS при active (exited) |
штатное состояние пустышки. О работе почты не говорит ничего: смотрите systemctl status postfix@-. |
разбор |
1/FAILURE у экземпляра |
самое частое: ошибка в настройках, занятый порт 25 или недоступный каталог очереди. Точную причину даёт postfix check. |
разбор |
пропущен по условию |
нет /etc/postfix/main.cf — unit не запускается и не помечается упавшим. В журнале строка про невыполненное условие. |
разбор |
Диагностика
Состояние настоящей службы. С этого надо начинать: статус postfix.service ни о чём не говорит.
systemctl status postfix@- --no-pager -lКакие экземпляры подключил генератор. Пустой список означает, что генератор не отработал.
systemctl list-dependencies postfix.service --no-pagerСгенерированные ссылки на экземпляры — прямая проверка работы генератора.
ls -l /run/systemd/generator/postfix.service.wants/ 2>/dev/nullПроверка настроек и прав на каталоги очереди: находит то, из-за чего экземпляр не стартует.
sudo postfix checkТолько изменённые настройки. Короткий вывод, по которому видно, что правили.
postconf -nОчередь и причины задержек: по ним понятно, проблема в отправке или в приёме.
mailq | tail -20Сообщения самих процессов postfix: они приходят в журнал под своими идентификаторами, а не от имени unit.
journalctl -t postfix/smtp -t postfix/cleanup -n 40 --no-pagerЕсть ли внутри изолированного корня свежая копия файла разрешения имён — частая причина отложенных писем.
sudo ls -l /var/spool/postfix/etc/resolv.confПараметры unit, которые тут важны
- Type=у пустышки `oneshot`, у экземпляра `forking`
- RemainAfterExit=именно из-за него пустышка вечно «активна»
- ExecStartPre=подготовка экземпляра перед запуском
- ExecReload=перезагрузка настроек без разрыва доставки
- ConditionPathExists=проверка наличия main.cf: пропуск вместо отказа
- DefaultInstance=экземпляр по умолчанию называется `-`
Частые вопросы
systemctl status postfix показывает active (exited) — это нормально?
Да, это штатное состояние. postfix.service в Debian и Ubuntu ничего не запускает: у него Type=oneshot и RemainAfterExit=yes. Настоящее состояние смотрите у экземпляра: systemctl status postfix@-.
Почему postfix@-.service нет в списке unit-файлов?
Потому что его никто не включал: ссылку на экземпляр создаёт генератор при каждой загрузке и при каждой перечитке описаний. Увидеть её можно в каталоге сгенерированных описаний или командой просмотра зависимостей postfix.service.
Письма откладываются с жалобой на ненайденный узел, хотя имена в системе разрешаются.
Процессы postfix работают в изолированном корне /var/spool/postfix, и файл разрешения имён им нужен внутри него. Копию туда переносит postfix-resolvconf.path. Проверьте, есть ли там свежая копия.
После установки postfix перестала работать прежняя почтовая служба.
Так и задумано: в описании объявлен конфликт с sendmail.service и exim4.service. Две почтовые службы на одном порту работать не могут, и systemd останавливает прежнюю.
Источники
- Пакет postfix 3.8.6-1ubuntu0.1 (Ubuntu 24.04): unit-файлы
- systemd.generator(7)
- systemd.path(5)
- Документация Postfix
- Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)