status=200/CHDIR в systemd
Код 200/CHDIR systemd выдаёт до запуска программы: он не сумел сделать рабочим каталог, указанный в WorkingDirectory=. Каталога либо нет, либо к нему нет доступа у пользователя службы, либо это вообще не каталог. Сама программа при этом не запускалась.
Что это значит
Смена рабочего каталога — один из первых шагов подготовки процесса, и выполняется он уже после перехода на пользователя из User=. Поэтому проверять доступ надо от имени этого пользователя, а не от root: у root доступ есть почти всегда, и это сбивает с толку.
Отдельный случай — каталог на сетевом или отдельном разделе. На момент запуска службы он может быть ещё не смонтирован, и тогда 200/CHDIR появляется только после перезагрузки, а при ручном перезапуске всё работает.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Каталога не существует
Опечатка в пути, каталог удалён или ещё не создан при первой установке. systemd сам каталог из
WorkingDirectory=не создаёт. -
У пользователя службы нет доступа к каталогу
Для перехода в каталог нужен бит x на нём и на всех каталогах по пути. Частая картина: каталог принадлежит root с правами 0700, а служба работает от отдельного пользователя.
-
Путь указан относительным
WorkingDirectory=принимает либо абсолютный путь, либо знак тильды для домашнего каталога пользователя. Запись видаWorkingDirectory=opt/myappдля systemd бессмысленна. -
Каталог находится на ещё не смонтированном разделе
Служба стартует раньше монтирования нужного раздела, и на его месте пока пустая точка монтирования или вообще ничего. После перезагрузки — отказ, при ручном запуске — успех.
-
Это не каталог, а файл или битая ссылка
Если по пути оказался обычный файл или символическая ссылка в никуда, переход завершится ошибкой ENOTDIR или ENOENT — код тот же.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Подтверждает код 200/CHDIR и показывает, что до строки запуска программы дело не дошло.
systemctl status myapp.service -l --no-pagersystemd печатает «Changing to the requested working directory failed» вместе с путём и причиной от ядра.
journalctl -xeu myapp.service --no-pager -n 30Показывает действующие значения после всех drop-in — то есть то, что systemd реально применил.
systemctl show myapp.service -p WorkingDirectory -p UserРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Опечатка в пути, каталог удалён или ещё не создан при первой установке. systemd сам каталог из
WorkingDirectory=не создаёт.
- Как проверить
-
Проверьте существование пути целиком, а не только последнего каталога.
systemctl cat myapp.service | grep -i workingdirectory ls -ld /opt/myapp
- Как исправить
-
Создайте каталог и назначьте владельца, от имени которого работает служба. Для каталогов в /var/lib, /var/cache и /run удобнее не создавать их вручную, а поручить systemd через
StateDirectory=,CacheDirectory=иRuntimeDirectory=.sudo install -d -o app -g app -m 0750 /opt/myapp
- Почему происходит
- Для перехода в каталог нужен бит x на нём и на всех каталогах по пути. Частая картина: каталог принадлежит root с правами 0700, а служба работает от отдельного пользователя.
- Как проверить
-
Проверьте доступ именно от пользователя службы.
sudo -u app sh -c 'cd /opt/myapp && echo доступ есть'
- Как исправить
-
Исправьте владельца или права. Осторожнее с
chmod -R 777: это снимает проблему и создаёт новую.sudo chown -R app:app /opt/myapp && sudo chmod 750 /opt/myapp
- Почему происходит
WorkingDirectory=принимает либо абсолютный путь, либо знак тильды для домашнего каталога пользователя. Запись видаWorkingDirectory=opt/myappдля systemd бессмысленна.
- Как проверить
- Посмотрите, начинается ли значение с косой черты.
- Как исправить
-
Допишите путь от корня целиком. Относительных путей systemd не разбирает: понятия «текущий каталог» у него в этот момент нет, поэтому дополнять значение нечем.
WorkingDirectory=/opt/myapp
- Почему происходит
- Служба стартует раньше монтирования нужного раздела, и на его месте пока пустая точка монтирования или вообще ничего. После перезагрузки — отказ, при ручном запуске — успех.
- Как проверить
-
Сравните время монтирования и время запуска службы в журнале загрузки.
systemctl list-dependencies --before myapp.service systemctl status data.mount
- Как исправить
-
Добавьте зависимость от точки монтирования. Самый короткий способ —
RequiresMountsFor=: systemd сам найдёт нужный mount-unit по пути.[Unit] RequiresMountsFor=/opt/myapp
- Почему происходит
- Если по пути оказался обычный файл или символическая ссылка в никуда, переход завершится ошибкой ENOTDIR или ENOENT — код тот же.
- Как проверить
-
Посмотрите тип объекта по пути.
ls -ld /opt/myapp && readlink -f /opt/myapp
- Как исправить
- Исправьте путь или замените файл настоящим каталогом.
Пример вывода
Каталог из WorkingDirectory= не создан. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
× myapp.service - My application
Active: failed (Result: exit-code) since Mon 2026-09-14 12:30:02 MSK; 2s ago
Process: 5120 ExecStart=/usr/local/bin/myapp (code=exited, status=200/CHDIR)
Main PID: 5120 (code=exited, status=200/CHDIR)
systemd[5120]: myapp.service: Changing to the requested working directory failed: No such file or directory
systemd[1]: myapp.service: Main process exited, code=exited, status=200/CHDIR
systemd[1]: myapp.service: Failed with result 'exit-code'.
Частые вопросы
Можно ли сделать каталог необязательным?
Да, поставьте дефис перед путём: WorkingDirectory=-/opt/myapp. Тогда при отсутствии каталога systemd не станет считать это ошибкой и запустит программу в корне. Для большинства служб это не то, что нужно, но для одноразовых задач бывает удобно.
Связанные ошибки
- status=203/EXEC в systemd Код 203/EXEC означает, что systemd не смог выполнить программу из ExecStart=. Разбор причин: путь, права, интерпретатор, синтаксис оболочки.
- status=217/USER в systemd Код 217/USER означает, что systemd не смог определить или сменить пользователя из User=. Разбор причин: пользователя нет, имя недопустимо, конфликт с DynamicUser.
- Permission denied в журнале службы Отказ в доступе у службы systemd: права на файл, каталоги по пути, пользователь службы, параметры изоляции, SELinux и AppArmor.
- status=233/RUNTIME_DIRECTORY в systemd Код 233/RUNTIME_DIRECTORY: не удалось подготовить каталог службы в /run из RuntimeDirectory=. Права, режим, удаление при остановке.
- No such file or directory в журнале службы Служба не находит файл или каталог. Разбор: путь, момент запуска, изоляция unit-файла, символические ссылки, приватный /tmp.
- MySQL: Can't open the mysql.plugin table и повреждение системных таблиц MySQL не запускается: недоступны или повреждены системные таблицы. Права на каталог данных, версия схемы, восстановление.
- PostgreSQL: data directory has invalid permissions Кластер PostgreSQL не запускается из-за прав на каталог данных. Требование 0700 или 0750 и как вернуть владельца.
- nginx 403 Forbidden и Permission denied на файлы сайта nginx отдаёт 403: нет прав на файлы сайта, закрыт каталог по пути, мешает SELinux или AppArmor, нет индексного файла.
Где встречается чаще всего
Источники
-
systemd.exec(5)
200 EXIT_CHDIR: «Changing to the requested working directory failed», см. WorkingDirectory=. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено на unit с несуществующим каталогом и на каталоге 0700, принадлежащем root, при User=app.