Урок курса

Фоновые процессы и автозапуск: systemd unit и journalctl

DevOps-инженер с нуля: полный курс

Когда мы запускали веб-приложение в терминале, оно занимало сеанс целиком: пока сервер работает, в этой же консоли нельзя выполнять другие команды, а закрытие окна или обрыв SSH-сессии сразу гасит процесс. Чтобы программа работала непрерывно в фоне и сама поднималась при перезагрузке системы, управление ей передают системному менеджеру.

1. Устройство service-файла в systemd

В Ubuntu главным процессом инициализации операционной системы выступает systemd. Он запускается ядром первым (получает идентификатор PID 1) и управляет фоновыми программами. Каждая служба описывается текстовым конфигурационным файлом — юнитом (unit file). Пользовательские службы операционной системы хранятся в каталоге /etc/systemd/system/ и имеют суффикс .service.

Файл конфигурации состоит из трёх ключевых секций:

  1. [Unit] — содержит общие метаданные и зависимости. Директива Description задаёт человекочитаемое описание сервиса, которое будет видно в статусе и системных отчётах.
  2. [Service] — определяет параметры запуска процесса. Параметр User указывает, от чьего имени запускать приложение. Запуск от непривилегированного пользователя, а не от root, ограничивает возможный ущерб при уязвимости в коде. WorkingDirectory задаёт текущую папку для процесса при старте. Параметр ExecStart задаёт команду, которую менеджер выполнит для старта приложения. Директива Restart=on-failure указывает systemd автоматически перезапускать упавшую программу, если она завершилась с ненулевым кодом возврата или была аварийно остановлена сигналом.
  3. [Install] — содержит инструкции по включению службы в автозагрузку. Строка WantedBy=multi-user.target привязывает сервис к стандартному многопользовательскому режиму, в котором операционная система загружается при обычном старте без графической оболочки.

В строке ExecStart особенно важно указать полный абсолютный путь к интерпретатору виртуального окружения проекта: /home/student/devops-demo/.venv/bin/python. Если написать просто python, systemd обратится к системному интерпретатору по стандартным системным путям, где нет библиотек, установленных в изолированное окружение приложения.

2. Создание и настройка сервиса для приложения

Перед тем как доверить запуск сервису, нужно убедиться, что порт 8000 свободен. Если тестовое приложение всё ещё запущено вручную в консоли, остановите его сочетанием клавиш Ctrl+C в соответствующем окне терминала.

Каталог /etc/systemd/system/ принадлежит суперпользователю. Создайте в нём файл службы с помощью редактора nano:

sudo nano /etc/systemd/system/devops-demo.service

Система запросит пароль учётной записи student. При вводе символы на экране не отображаются — это стандартное поведение Linux. Введите пароль и нажмите Enter.

В открывшемся окне редактора вставьте следующую конфигурацию:

[Unit]
Description=DevOps Demo Service

[Service]
User=student
WorkingDirectory=/home/student/devops-demo
ExecStart=/home/student/devops-demo/.venv/bin/python /home/student/devops-demo/app.py --host 127.0.0.1 --port 8000
Restart=on-failure

[Install]
WantedBy=multi-user.target

Обратите внимание на аргумент --host 127.0.0.1. Мы намеренно привязываем сервер к локальному интерфейсу обратной петли (loopback) виртуальной машины. В такой конфигурации служебный порт не торчит наружу, а само приложение доступно только процессам внутри этой же операционной системы. Сохраните файл (Ctrl+O, затем Enter) и закройте редактор (Ctrl+X).

3. Управление службой и автозапуск через systemctl

После создания нового файла или изменения существующего менеджер systemd ничего о нём не знает, пока его конфигурацию не перечитают с диска. Для этого выполняется команда перезагрузки конфигурации:

sudo systemctl daemon-reload

Команда systemctl enable отвечает только за автозапуск: она создаёт символическую ссылку на юнит в каталоге целевого режима multi-user.target.wants. Если вызвать sudo systemctl enable devops-demo без дополнительных параметров, служба будет добавлена в очередь загрузки ОС, но прямо сейчас не запустится — процесс останется неактивным. Чтобы зарегистрировать автозапуск и запустить сервис одной командой, передают флаг --now:

Связь unit-файла, симлинка автозапуска, процесса Python, журнала systemd и утилиты journalctl
Автозапуск, запуск службы и сбор логов в systemd
sudo systemctl enable --now devops-demo

Проверить состояние службы можно командой status:

systemctl status devops-demo

В выводе отобразится блок информации: статус active (running), идентификатор запущенного процесса (PID), используемый объём памяти и последние строки сообщений. Для автоматических проверок в скриптах используют команду systemctl is-active devops-demo. Она выводит текущее состояние службы (например, active, inactive, failed или activating), а результат сообщает через код завершения: 0, если служба активна, и ненулевой код при любом другом состоянии.

Проверим работу службы запросом внутри гостевой виртуальной машины:

curl http://127.0.0.1:8000/health

Сервер вернёт ответ от приложения. Однако если вы попытаетесь открыть http://127.0.0.1:18000 в браузере на основном компьютере с Windows, соединение будет сброшено. Правило проброса портов VirtualBox NAT перенаправляет трафик с порта 18000 хоста на внешний сетевой адрес гостевой виртуальной машины, а процесс слушает только внутренний интерфейс 127.0.0.1. Прямой доступ снаружи появится позже, когда перед приложением будет настроен обратный прокси-сервер.

4. Поиск ошибок запуска в журнале journalctl

Фоновые службы не имеют собственного терминала, поэтому стандартные потоки вывода (stdout) и ошибок (stderr) перехватывает системный журнал. Для чтения этих записей используется утилита journalctl.

Посмотрим, как выглядит диагностика типового сбоя на практике. Допустим, в конфигурации сервиса была допущена опечатка в пути к исполняемому файлу. Откройте юнит через sudo nano /etc/systemd/system/devops-demo.service и временно измените в ExecStart путь к несуществующему файлу, например /home/student/devops-demo/.venv/bin/python-broken. Сохраните изменения и примените их:

sudo systemctl daemon-reload
sudo systemctl restart devops-demo

Обратите внимание: сама команда restart может выполниться без единой ошибки и вернуться в командную строку с нулевым кодом. В нашем юните не указан параметр Type=, поэтому systemd использует тип запуска по умолчанию — simple. При таком типе менеджер считает запуск принятым сразу после создания процесса, ещё до того, как система попытается выполнить саму команду по указанному пути. Успешное завершение systemctl restart говорит лишь о том, что запрос на перезапуск принят, но не доказывает, что приложение действительно работает.

Проверим фактическое состояние службы:

systemctl status devops-demo

В строке Active: вместо ожидаемого active (running) отобразится failed (Result: exit-code) либо промежуточное состояние activating (auto-restart), пока действует правило Restart=on-failure. В подробностях процесса появится статус завершения (code=exited, status=203/EXEC).

Чтобы увидеть причину сбоя полностью, запросим журнал сервиса через journalctl:

journalctl -u devops-demo -n 50 --no-pager

Флаг -u devops-demo отбирает сообщения конкретного юнита. Флаг -n 50 ограничивает вывод последними 50 строками. Флаг --no-pager отключает интерактивный просмотрщик, выводя текст прямо в поток терминала без необходимости нажимать q для выхода.

В выводе журнала отобразится сообщение ядра о неудачной попытке запуска:

Failed at step EXEC spawning /home/student/devops-demo/.venv/bin/python-broken: No such file or directory

Код ошибки 203/EXEC означает, что systemd попытался запустить процесс, но исполняемый файл по указанному пути не найден или к нему нет прав на выполнение.

Теперь вернём сервис в рабочее состояние. Откройте /etc/systemd/system/devops-demo.service, восстановите исходный путь /home/student/devops-demo/.venv/bin/python, сохраните файл и выполните полный цикл обновления:

sudo systemctl daemon-reload
sudo systemctl restart devops-demo

Убедимся, что служба восстановилась и отвечает на запросы:

systemctl status devops-demo
curl http://127.0.0.1:8000/health

Статус снова показывает active (running), а curl возвращает штатный ответ веб-сервера. Любая правка параметров юнита на диске всегда требует вызова daemon-reload, иначе systemd продолжит использовать кэшированную конфигурацию из оперативной памяти.

Задача 1

После создания файла /etc/systemd/system/devops-demo.service были выполнены команды:

sudo systemctl daemon-reload
sudo systemctl enable devops-demo

Сразу после этого проверка curl http://127.0.0.1:8000/health завершилась ошибкой Connection refused. Почему сервис не ответил на запрос?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 2

В выводе systemctl status devops-demo появилась ошибка: Process: ... ExecStart=/home/student/devops-demo/venv/bin/python app.py (code=exited, status=203/EXEC) Журнал journalctl -u devops-demo поясняет сбой строкой: Failed at step EXEC spawning /home/student/devops-demo/venv/bin/python: No such file or directory Какая причина вызвала ошибку и как её исправить?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 3

Служба запущена в виртуальной машине со строкой: ExecStart=/home/student/devops-demo/.venv/bin/python /home/student/devops-demo/app.py --host 127.0.0.1 --port 8000 Запрос curl http://127.0.0.1:8000/health внутри виртуалки возвращает 200 OK. В VirtualBox настроен проброс портов NAT 18000 -> 8000. Однако обращение http://127.0.0.1:18000/health из браузера хоста завершается ошибкой соединения. Почему сервис недоступен с хоста?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 4

В файле /etc/systemd/system/devops-demo.service изменили значение параметра Restart=on-failure. Сразу после сохранения выполнили команду:

sudo systemctl restart devops-demo

Терминал вывел предупреждение: Warning: The unit file, source configuration file or drop-ins of devops-demo.service changed on disk. Run 'systemctl daemon-reload' to reload units. Почему появилось это предупреждение?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 5

Изоляция внутренней службы очередей

В рабочей папке подготовлен черновик queue-preview.service для внутренней службы очередей. Приложение и его виртуальное окружение уже размещены в /srv/queue-preview: запуск должен выполняться через /srv/queue-preview/.venv/bin/python для программы /srv/queue-preview/app.py, а в системе уже существует непривилегированный пользователь worker.

Службу нужно настроить для запуска от пользователя worker непосредственно из каталога проекта с обращениями только из самой виртуальной машины на порт 8094 и автоматическим повторным запуском после аварийного завершения. Часть параметров в предоставленном файле противоречит этим условиям. Исправьте конфигурацию в соответствии с требованиями, сохранив секции [Unit], [Service] и [Install], их исходное расположение, описание сервиса, привязку к multi-user.target и остальные не затронутые строки.

В редакторе уже выведен блок доставки файла: строки до и после конфигурации оставьте без изменений и отредактируйте только содержимое queue-preview.service между ними. Сохраните готовый файл в рабочей папке с точным форматом заготовки и завершающим переводом строки. Устанавливать и запускать службу не требуется.

РешениеBash

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Продолжить с сохранением прогресса

Перейдите к уроку в учебном кабинете.

Перейти к интерактивному уроку