Урок курса
Фоновые процессы и автозапуск: systemd unit и journalctl
DevOps-инженер с нуля: полный курсКогда мы запускали веб-приложение в терминале, оно занимало сеанс целиком: пока сервер работает, в этой же консоли нельзя выполнять другие команды, а закрытие окна или обрыв SSH-сессии сразу гасит процесс. Чтобы программа работала непрерывно в фоне и сама поднималась при перезагрузке системы, управление ей передают системному менеджеру.
1. Устройство service-файла в systemd
В Ubuntu главным процессом инициализации операционной системы выступает systemd. Он запускается ядром первым (получает идентификатор PID 1) и управляет фоновыми программами. Каждая служба описывается текстовым конфигурационным файлом — юнитом (unit file). Пользовательские службы операционной системы хранятся в каталоге /etc/systemd/system/ и имеют суффикс .service.
Файл конфигурации состоит из трёх ключевых секций:
[Unit]— содержит общие метаданные и зависимости. ДирективаDescriptionзадаёт человекочитаемое описание сервиса, которое будет видно в статусе и системных отчётах.[Service]— определяет параметры запуска процесса. ПараметрUserуказывает, от чьего имени запускать приложение. Запуск от непривилегированного пользователя, а не от root, ограничивает возможный ущерб при уязвимости в коде.WorkingDirectoryзадаёт текущую папку для процесса при старте. ПараметрExecStartзадаёт команду, которую менеджер выполнит для старта приложения. ДирективаRestart=on-failureуказываетsystemdавтоматически перезапускать упавшую программу, если она завершилась с ненулевым кодом возврата или была аварийно остановлена сигналом.[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:

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 между ними. Сохраните готовый файл в рабочей папке с точным форматом заготовки и завершающим переводом строки. Устанавливать и запускать службу не требуется.
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Продолжить с сохранением прогресса
Перейдите к уроку в учебном кабинете.
