Как проверить unit-файл systemd до daemon-reload и запуска службы
Проверяем полный unit-кандидат через systemd-analyze verify, разбираем код возврата, опечатку в директиве, отсутствующий исполняемый файл и потерянную зависимость — без daemon-reload и запуска службы.

В этой статье
Ошибка в unit-файле лучше обнаружить до daemon-reload и запуска службы. Для полного файла-кандидата выполните systemd-analyze verify --man=no ./candidate.service: код 0 позволяет перейти к следующей проверке, а ненулевой код оставляет изменение неподготовленным.
Ниже — воспроизводимая проверка на Ubuntu 24.04, systemd 255 (255.4-1ubuntu8.17), выполненная 10 октября 2026 года. Все четыре unit-файла находились в отдельном рабочем каталоге. Команды systemctl daemon-reload, systemctl start, systemctl restart и перезагрузка не запускались.
Что проверяет systemd-analyze verify
Документация systemd-analyze указывает, что verify загружает переданные unit-файлы, сообщает найденные ошибки и также рассматривает другие unit, на которые они ссылаются. Поэтому результат зависит не только от синтаксиса одной строки, но и от доступных зависимостей и исполняемых файлов.
Это статическая проверка перед применением. Она не отправляет новую конфигурацию работающему менеджеру systemd и не запускает службу. Но и код 0 не доказывает, что приложение подключится к базе, прочитает секрет, получит сеть или успешно отработает под назначенным пользователем.
Сначала зафиксируйте версию
systemd-analyze --version
В тестовой среде первая строка вывода была systemd 255 (255.4-1ubuntu8.17). В другой версии набор проверок и формулировки диагностики могут отличаться, поэтому версию полезно сохранить вместе с результатом.
Подготовьте отдельный unit-кандидат
Минимальный учебный файл назван candidate.service. Расширение важно: по нему systemd определяет тип unit. В примере команда только печатает строку; сам сервис в этой проверке не запускался.
[Unit]
Description=Training verification unit
[Service]
Type=oneshot
ExecStart=/usr/bin/printf systemd-verify-ok
Для Type=oneshot и правил ExecStart= ориентируйтесь на справку systemd.service. Учебный пример не переносит настройки пользователя, каталога, переменных окружения и ограничений из реального сервиса.
Проверьте файл, не применяя его
systemd-analyze verify --man=no ./candidate.service
Параметр --man=no отключает проверку наличия страниц руководства, если в unit используется Documentation=man:. Он не отключает разбор unit, зависимостей и исполняемого файла.
systemd-analyze verify --man=no ./candidate.service; printf 'exit=%s\n' "$?"
Исправный учебный файл не вывел сообщений и вернул exit=0. Повторная проверка дала тот же результат; контрольные суммы файлов до и после совпали.

Три ошибки, которые обнаружились в тесте
В первом дефектном файле директива ExecStart была написана как ExecStrat. Проверка сообщила Unknown key name 'ExecStrat', затем отказалась принимать сервис без команды запуска и вернула 1.
ExecStrat=/usr/bin/printf systemd-verify-ok
Во втором файле путь из ExecStart= отсутствовал. Диагностика Command /opt/example/bin/not-installed is not executable: No such file or directory сопровождалась кодом 1.
ExecStart=/opt/example/bin/not-installed
Третий файл ссылался через Requires= и After= на unit, которого не было в доступных путях загрузки. Проверка сообщила Unit definitely-missing-example.service not found и вернула 1.
Requires=definitely-missing-example.service
After=definitely-missing-example.service
Все три сбоя были воспроизведены дважды. Исправный файл возвращал 0, а опечатка в директиве, отсутствующий исполняемый файл и отсутствующая зависимость — 1.

Не теряйте код возврата
Не передавайте вывод сразу в grep или head: без специальных настроек оболочки вы можете получить код последней команды конвейера вместо кода systemd-analyze. Проще сначала использовать условие и отдельно сохранить диагностику.
if systemd-analyze verify --man=no ./candidate.service >./verify.log 2>&1; then
printf 'verify=ok\n'
else
printf 'verify=stop\n'
sed -n '1,80p' ./verify.log
fi
В отдельном повторе этот шаблон вывел verify=ok для исправного файла и verify=stop для файла с отсутствующим исполняемым путем. Файл verify.log может содержать пути и имена внутренних unit; храните его с подходящими правами и не публикуйте без просмотра.
Почему пустой вывод ещё не означает готовность
Проверка видит доступные ей unit и пути. В другой системе зависимость или исполняемый файл могут присутствовать либо отсутствовать.
Полный unit и drop-in — разные объекты. Отдельный файл
override.confнельзя оценивать как самостоятельный сервис без исходного unit и реального порядка наложения.Существование программы не доказывает, что она запустится под
User=, получит доступ кWorkingDirectory=, сокету, сертификату или секрету.Проверка не воспроизводит сетевую готовность, лимиты ресурсов, sandbox-настройки, состояние базы и пользовательский сценарий.
Сгенерированные и шаблонные unit требуют той же версии генераторов и корректного экземпляра; проверка абстрактного шаблона может не описывать рабочий экземпляр.
Порядок безопасной приёмки
Сохраните исходный unit и все drop-in отдельно; зафиксируйте версию systemd.
Сформируйте полный кандидат тем же способом, которым его создаёт система управления конфигурацией.
Запустите
systemd-analyze verifyдля кандидата и устраните каждое сообщение, а не только ошибки синтаксиса.Сопоставьте
ExecStart=,User=, каталоги, зависимости и переменные окружения с планом изменения.Только после согласования применяйте unit штатным способом и выполняйте
daemon-reloadв управляемом окне.Отдельно проверьте фактический запуск, состояние, журнал и пользовательскую функцию сервиса; держите готовым возврат исходного unit.
Условие остановки простое: любой неизвестный ключ, отсутствующий исполняемый файл, потерянная зависимость или ненулевой код оставляет кандидат неподготовленным. Код 0 закрывает только статическую часть. А дальше нужна проверка именно того процесса и сервиса, которые должны работать после изменения.
It is better to detect an error in a unit file before daemon-reload and starting the service. For a complete candidate file, run systemd-analyze verify --man=no ./candidate.service: exit code 0 allows you to proceed to the next check, while a nonzero exit code means the change is not ready to apply.
Below is a reproducible check on Ubuntu 24.04, systemd 255 (255.4-1ubuntu8.17), performed on October 10, 2026. All four unit files were in a separate working directory. The commands systemctl daemon-reload, systemctl start, and systemctl restart were not run, and the system was not rebooted.
What systemd-analyze verify checks
The systemd-analyze documentation states that verify loads the supplied unit files, reports errors it finds, and also examines other units they reference. The result therefore depends not only on the syntax of an individual line, but also on the available dependencies and executables.
This is a static check before deployment. It does not send the new configuration to the running systemd manager or start the service. However, even exit code 0 does not prove that the application will connect to its database, read a secret, gain network access, or work successfully as the configured user.
Record the version first
systemd-analyze --version
In the test environment, the first output line was systemd 255 (255.4-1ubuntu8.17). Other versions may perform different checks and use different diagnostic wording, so it is useful to save the version with the result.
Prepare a separate candidate unit
The minimal training file is named candidate.service. The extension matters: systemd uses it to determine the unit type. In this example, the command only prints a string; the service itself was not started during the check.
[Unit]
Description=Training verification unit
[Service]
Type=oneshot
ExecStart=/usr/bin/printf systemd-verify-ok
For Type=oneshot and the rules governing ExecStart=, refer to the systemd.service manual. The training example does not include the user, directory, environment variable, or restriction settings from a real service.
Check the file without applying it
systemd-analyze verify --man=no ./candidate.service
The --man=no option disables checks for the existence of manual pages when the unit uses Documentation=man:. It does not disable the analysis of the unit, its dependencies, or its executable.
systemd-analyze verify --man=no ./candidate.service; printf 'exit=%s\n' "$?"
The valid training file produced no messages and returned exit=0. A repeat check gave the same result; the file checksums matched before and after the checks.

Three errors detected in the test
In the first defective file, the ExecStart directive was misspelled as ExecStrat. The check reported Unknown key name 'ExecStrat', then refused to accept a service without a startup command and returned 1.
ExecStrat=/usr/bin/printf systemd-verify-ok
In the second file, the path specified in ExecStart= did not exist. The diagnostic Command /opt/example/bin/not-installed is not executable: No such file or directory was accompanied by exit code 1.
ExecStart=/opt/example/bin/not-installed
The third file used Requires= and After= to reference a unit that was absent from the available load paths. The check reported Unit definitely-missing-example.service not found and returned 1.
Requires=definitely-missing-example.service
After=definitely-missing-example.service
All three failures were reproduced twice. The valid file returned 0, while the misspelled directive, missing executable, and missing dependency returned 1.

Do not lose the exit code
Do not pipe the output straight into grep or head: without special shell settings, you may get the exit code of the last command in the pipeline instead of the exit code from systemd-analyze. It is simpler to use a conditional first and save the diagnostics separately.
if systemd-analyze verify --man=no ./candidate.service >./verify.log 2>&1; then
printf 'verify=ok\n'
else
printf 'verify=stop\n'
sed -n '1,80p' ./verify.log
fi
In a separate repeat test, this pattern printed verify=ok for the valid file and verify=stop for the file with a missing executable path. The verify.log file may contain paths and internal unit names; store it with suitable permissions and review it before publishing.
Why empty output does not mean the unit is ready
The check sees the units and paths available to it. A dependency or executable may be present or absent on a different system.
A complete unit and a drop-in are different objects. A separate
override.conffile cannot be assessed as a standalone service without the original unit and the actual order in which the configuration is layered.The existence of a program does not prove that it will run under
User=or gain access toWorkingDirectory=, a socket, a certificate, or a secret.The check does not reproduce network readiness, resource limits, sandbox settings, database state, or the user scenario.
Generated and template units require the same generator versions and a valid instance; checking an abstract template may not describe the instance used in production.
A safe acceptance procedure
Save the original unit and all drop-ins separately; record the systemd version.
Build the complete candidate in the same way as the configuration management system generates it.
Run
systemd-analyze verifyfor the candidate and resolve every diagnostic message, not just syntax errors.Compare
ExecStart=,User=, directories, dependencies, and environment variables against the change plan.Only after approval should you deploy the unit through the standard procedure and run
daemon-reloadin a controlled maintenance window.Separately check the actual startup, status, journal, and the service function used by its users; keep a way to restore the original unit ready.
The stop condition is simple: any unknown key, missing executable, missing dependency, or nonzero exit code means the candidate is not ready. Exit code 0 completes only the static checks. The actual process and service that must work after the change still need to be tested.





Обсуждение 0
Делись опытом и задавай вопросы. Комментарии без ссылок появляются после проверки редактором.
Пока никто не написал. Начни обсуждение.