Когда Linux-служба не запускается, одного сообщения systemctl start обычно недостаточно. Причина чаще всего находится в статусе юнита и журнале: неверный путь ExecStart, права пользователя, ошибка конфигурации, занятый порт, ограничение sandbox или неготовая зависимость. Ниже — последовательная диагностика systemd-служб без отключения защитных механизмов вслепую.
Команды рассчитаны на дистрибутивы с systemd. В примерах используется example.service; замените его своим именем. Чтение статуса безопасно, а перезапуск и сброс ошибки меняют состояние службы — выполняйте их после проверки влияния на production.
1. Зафиксируйте состояние
Не начинайте с многократного перезапуска. Сначала сохраните состояние, последний результат, путь к unit-файлу и ожидающие задания.
sudo systemctl status example.service --no-pager -l
sudo systemctl show example.service -p LoadState -p ActiveState -p SubState -p Result -p ExecMainCode -p ExecMainStatus -p FragmentPath -p DropInPaths
sudo systemctl list-jobs
В status важны строки Loaded, Active и Process. systemctl show удобен для точечных свойств, а list-jobs показывает зависшие задания. Точно скопируйте имя unit: экземпляр шаблона может называться worker@1.service.
Для сайтов, ботов и pet-проектов можно использовать Beget: виртуальный хостинг от 420 ₽/мес., VPS от 330 ₽/мес. и тестовый период.
2. Прочитайте журнал именно этой службы
sudo journalctl -u example.service -b --no-pager -n 200
sudo journalctl -u example.service --since '-1 hour' -p warning --no-pager
sudo journalctl -fu example.service
systemd запускает процесс отдельно от интерактивной оболочки, поэтому stdout и stderr ищите в journal. Флаг -u фильтрует unit, -b — текущую загрузку, -f показывает новые записи. Журнал предыдущей загрузки проверяется через journalctl -u example.service -b -1, если он сохраняется между перезагрузками.
3. Проверьте фактический unit и drop-in
sudo systemctl cat example.service
sudo systemctl show example.service -p FragmentPath -p DropInPaths -p UnitFileState
sudo systemd-analyze verify /etc/systemd/system/example.service
sudo systemctl daemon-reload
systemctl cat показывает основной файл и переопределения. Не редактируйте пакетные файлы в /usr/lib/systemd/system или /lib/systemd/system: обновление может затереть изменения. Для локальной настройки используйте /etc/systemd/system и drop-in через systemctl edit. После изменения unit нужен daemon-reload; он не перезапускает приложение автоматически.
4. Частые причины отказа
Неверный ExecStart
В ExecStart= указывайте абсолютный путь. Строка не исполняется через shell автоматически: |, >, && и $(...) не работают как в терминале. Для сложной логики создайте отдельный проверенный скрипт. Не храните токены в unit-файле и не печатайте секреты в журнал.
# Неправильно для обычного ExecStart
ExecStart=/usr/bin/app --config /etc/example/app.conf >> /var/log/example.log
# Надёжнее: приложению задать конфигурацию, вывод оставить в journal
ExecStart=/usr/bin/app --config /etc/example/app.conf
Type, процесс и рабочий каталог
Для процесса, который остаётся на переднем плане, обычно подходит Type=simple. Для конечной задачи — Type=oneshot. Для daemon, который сам уходит в фон, может потребоваться Type=forking и корректный PID-файл. Не добавляйте RemainAfterExit=yes, чтобы скрыть преждевременное завершение: сначала выясните ожидаемое поведение приложения. Задайте WorkingDirectory=, если программа зависит от текущего каталога.
Пользователь и права
getent passwd example
namei -l /srv/example/config.yml
sudo -u example test -r /srv/example/config.yml
sudo -u example test -w /var/lib/example
Проверьте пользователя User=, группу и право прохода по каждому родительскому каталогу. Не исправляйте ошибку командами chmod -R 777 или массовой сменой владельца: это может открыть секреты. Выдайте минимум прав только на нужные пути.
Порт, диск и память
sudo ss -ltnp
df -h
df -i
sudo journalctl -k -b -p warning --no-pager
Address already in use означает, что сначала нужно найти владельца порта. Проверьте второй экземпляр приложения, свободное место, inode и сообщения OOM killer. Не повышайте лимиты и не отключайте контроль памяти без причины.
Зависимости и сеть
After= задаёт порядок, но не гарантирует доступность удалённого API, DNS или базы данных. Wants= и Requires= не заменяют таймауты, повторы и health-check внутри приложения. Не добавляйте network-online.target всем службам автоматически: результат зависит от сетевого менеджера.
SELinux, AppArmor и sandbox
Отказ доступа может быть вызван SELinux, AppArmor или директивами systemd. Проверьте audit/kernel-журналы и systemd-analyze security example.service. Не отключайте защиту в production ради проверки; изменяйте одну конкретную директиву в тестовой среде и фиксируйте результат.
5. Исправьте причину и выполните один перезапуск
sudo systemctl daemon-reload
sudo systemctl cat example.service
sudo systemctl restart example.service
sudo systemctl status example.service --no-pager -l
sudo journalctl -u example.service -b --no-pager -n 100
Состояние failed — итог, а не диагноз. Сопоставьте Result, ExecMainCode, ExecMainStatus и время в журнале с логом приложения. systemctl reset-failed example.service очищает состояние и счётчик запуска, но не исправляет конфигурацию, поэтому выполняйте его после устранения причины.
6. Автоматический перезапуск без бесконечного цикла
[Service]
Restart=on-failure
RestartSec=5s
Автоперезапуск подходит не каждому приложению. Убедитесь, что повторный запуск безопасен и незавершённые операции не повреждают данные. Частые отказы увеличивают нагрузку и могут скрыть первичную ошибку; настройте лимиты запусков и оповещение.
Минимальный сценарий диагностики
UNIT='example.service'
sudo systemctl status "$UNIT" --no-pager -l
sudo journalctl -u "$UNIT" -b --no-pager -n 200
sudo systemctl cat "$UNIT"
sudo systemctl show "$UNIT" -p Result -p ExecMainCode -p ExecMainStatus -p FragmentPath -p DropInPaths
# только после исправления причины:
sudo systemctl reset-failed "$UNIT"
sudo systemctl start "$UNIT"
sudo systemctl status "$UNIT" --no-pager -l
Что приложить к обращению за помощью
- дистрибутив и версию systemd;
- точное имя unit и ожидаемое поведение;
- status и journal за нужный период без секретов;
- systemctl cat с удалёнными паролями, токенами и ключами;
- что изменилось перед отказом и какие проверки проведены.
Перед отправкой логов удалите токены, email, IP-адреса, пути пользователей и параметры подключения. Оставляйте только данные, необходимые для диагностики.
Частые вопросы
Почему systemctl start ничего не объяснил?
Терминал показывает итог задания, а вывод процесса обычно записывается в journal. Используйте systemctl status имя.service и journalctl -u имя.service -b.
После изменения unit действует старое значение. Почему?
Выполните systemctl daemon-reload, проверьте итог через systemctl cat и перезапустите службу только в безопасное окно.
Полезные материалы и помощь
Если проблема связана с расписанием, смотрите руководство по systemd timers вместо cron. Для журналов и аудита — материал про auditd и journald, для удалённого доступа — безопасную настройку SSH.
Для тестирования конфигурации можно использовать отдельный VPS: посмотреть VPS Beget. Это партнёрская ссылка; цены и условия определяет провайдер.
Официальные источники
Итог
При отказе systemd-службы сначала зафиксируйте status, свойства unit и журнал, затем проверьте фактический файл, пользователя, пути и зависимости. Исправляйте одну причину за раз, перечитывайте unit и подтверждайте результат новым статусом и логами. Такой порядок ускоряет диагностику и не заставляет ослаблять защиту без необходимости.
Подборка онлайн-курсов для разработчиков — Python, Java, веб и DevOps.
Разберём задачу и предложим понятный состав работ, срок и стоимость.
Статья может содержать партнёрские ссылки. Это не влияет на стоимость для вас, но помогает развивать блог.

