Сервис не находит config.yaml: задаём рабочий каталог systemd
Из каталога приложения команда запускается, а в systemd сообщает, что config.yaml не существует. Файл лежит рядом с исполняемым модулем, права выглядят подходящими, путь к программе в ExecStart абсолютный. Кажется, что всё необходимое уже задано. Но путь к программе и рабочий каталог процесса решают разные задачи.
Приложение может открыть config.yaml относительно текущего каталога, а не относительно своего исходного файла. Для системной службы без WorkingDirectory отправной точкой обычно будет корень файловой системы. Рядом с бинарным файлом менеджер служб автоматически не перемещается. То, что интерактивный запуск начинается с cd /opt/catalog, становится частью скрытого контракта запуска.
Сделать контракт явным
Если приложение рассчитано на относительные пути, задайте каталог непосредственно в службе. Ниже фрагмент для приложения, которое читает конфигурацию из каталога /opt/catalog и работает от отдельного пользователя catalog.
[Service]
User=catalog
WorkingDirectory=/opt/catalog
ExecStart=/opt/catalog/.venv/bin/python -m catalog --config config.yaml
Рабочий каталог не заменяет права доступа. Пользователю catalog всё равно нужны разрешения пройти по каталогам пути и прочитать файл. И он не заменяет абсолютный путь к интерпретатору: выбранное виртуальное окружение определяет зависимости, а WorkingDirectory определяет разрешение относительных имён.
Есть и другой хороший вариант: передавать /etc/catalog/config.yaml как абсолютный путь. Он особенно удобен, когда код разворачивается в каталог с номером версии, а конфигурация живёт отдельно. Тогда смена релиза не переносит настройки вместе с исходниками. При этом приложение может продолжать использовать рабочий каталог для других относительных файлов — шаблонов, миграций или локальных ресурсов. Проверьте все такие обращения, а не только первое сообщение об ошибке.
Смотреть на работающий процесс
После изменения unit на учебном сервере выполните daemon-reload и перезапустите службу. Сначала systemctl show catalog.service -p WorkingDirectory покажет настройку менеджера. Затем возьмите MainPID и посмотрите /proc/ИМЯ_PID/cwd через readlink. Это уже каталог процесса; приложение могло сменить его самостоятельно после запуска. Если процесс быстро падает, опирайтесь на журнал и временный диагностический вывод текущего каталога в самом приложении.
При проверке разделите два результата: исчезновение ошибки чтения и появление ожидаемого поведения с нужным конфигом. Иногда приложение вместо отсутствующего файла молча выбирает настройки по умолчанию. Полезно вывести в стартовом сообщении абсолютный путь к загруженному конфигу без секретных значений. Тогда видно, какой именно файл использован.
Перед передачей сервиса коллеге запишите в инструкции три независимые вещи: путь к программе, рабочий каталог и путь к конфигурации. Это короткое описание снимает зависимость от того, из какой папки человек однажды запускал команду вручную.
Продолжить практику
За одной настройкой unit обычно стоит весь путь сопровождения приложения: отдельный пользователь, права на данные, сеть, журналы и повторяемые операции. В программе курса «Linux и Bash для DevOps-инженеров» эти задачи собраны вокруг учебного сервера с приложением под systemd. В практике предусмотрены Bash-скрипты проверки состояния и резервного копирования, а также runbook для воспроизводимых поломок. Это подходящее продолжение, если хочется связать отдельные команды в понятный порядок диагностики.
Источник: официальная документация.
Другие задачи по теме: Запуск и жизненный цикл служб systemd.
Продолжить на практике
- Linux и Bash для DevOps-инженеров ↗
Linux для работы с серверами: процессы, права, systemd, сеть, диски и логи. Автоматизируйте повседневные задачи на Bash и разберите типичные сбои сервиса — от занятого порта до переполненного диска.
