Permission denied в журнале службы
Сообщение Permission denied значит, что ядро отказало в доступе к файлу, каталогу, сокету или устройству. У служб systemd источников отказа больше, чем кажется: помимо обычных прав действуют пользователь из User=, параметры изоляции unit-файла и модули безопасности.
Что это значит
Разбор идёт по порядку проверки. Сначала выясняем, от кого работает служба: systemctl show -p User. Затем — к чему именно ей отказали: путь почти всегда назван в сообщении. И только потом смотрим права, потому что чаще виноваты не они, а каталог по пути или изоляция.
Особенность, которая съедает больше всего времени: для доступа к файлу нужен бит x на каждом каталоге пути. Права 0644 на файле бесполезны, если родительский каталог закрыт как 0700 для другого владельца.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
У пользователя службы нет прав на файл или каталог
Служба работает от
User=, а файл принадлежит root или другому пользователю. В терминале под root всё открывается, и проблема кажется несуществующей. -
Закрыт один из каталогов по пути
Для обращения к файлу нужно право на вход в каждый каталог пути. Один закрытый каталог посередине делает недоступным всё, что ниже.
-
Путь закрыт параметрами изоляции unit-файла
ProtectSystem=strictделает /usr и /etc доступными только для чтения,ProtectHome=закрывает домашние каталоги,ReadOnlyPaths=— указанные пути. Права на диске при этом в полном порядке, а доступа нет. -
Запрещает SELinux или AppArmor
Модуль безопасности отказывает независимо от прав. Признак — отказ при верных правах и записи в журнале аудита.
-
Файловая система смонтирована только для чтения или с запретом исполнения
Параметры монтирования ro и noexec дают отказ при попытке записи или запуска, даже когда права разрешают.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Находит саму строку отказа: в ней обычно есть путь, к которому не дали доступ.
journalctl -u myapp.service -n 60 --no-pager | grep -i -E "denied|permission"Показывает права и владельца на каждом уровне пути — самый быстрый способ найти обрыв.
namei -l /путь/из/сообщенияОт кого фактически работает служба. Без этого проверять права бессмысленно.
systemctl show myapp.service -p User -p Group -p SupplementaryGroupsПараметры изоляции: вторая по частоте причина отказа при верных правах.
systemctl show myapp.service | grep -E "^Protect|^Private|Paths"Решение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Служба работает от
User=, а файл принадлежит root или другому пользователю. В терминале под root всё открывается, и проблема кажется несуществующей.
- Как проверить
-
Проверьте доступ от имени пользователя службы, а не от своего.
systemctl show myapp.service -p User sudo -u app test -r /etc/myapp/config.yml && echo читается || echo отказ
- Как исправить
-
Передайте нужные файлы пользователю службы или добавьте его в группу-владельца. Рекурсивный доступ всем подряд создаёт больше проблем, чем решает.
sudo chown -R app:app /var/lib/myapp && sudo chmod 750 /var/lib/myapp
- Почему происходит
- Для обращения к файлу нужно право на вход в каждый каталог пути. Один закрытый каталог посередине делает недоступным всё, что ниже.
- Как проверить
-
Пройдите по пути целиком.
namei -l /var/lib/myapp/data/state.db
- Как исправить
-
Откройте вход в промежуточные каталоги (бит x) для пользователя или группы службы. Команда
namei -lпоказывает, на каком уровне обрыв.sudo chmod o+x /var/lib/myapp
- Почему происходит
ProtectSystem=strictделает /usr и /etc доступными только для чтения,ProtectHome=закрывает домашние каталоги,ReadOnlyPaths=— указанные пути. Права на диске при этом в полном порядке, а доступа нет.
- Как проверить
-
Посмотрите действующие параметры изоляции.
systemctl show myapp.service | grep -E "Protect|ReadOnlyPaths|ReadWritePaths|Inaccessible|PrivateTmp"
- Как исправить
-
Разрешите нужный путь точечно через
ReadWritePaths=, а не снимайте изоляцию целиком.sudo systemctl edit myapp.service # ReadWritePaths=/var/lib/myapp
- Почему происходит
- Модуль безопасности отказывает независимо от прав. Признак — отказ при верных правах и записи в журнале аудита.
- Как проверить
-
Посмотрите режим модуля и отказы.
getenforce 2>/dev/null; sudo aa-status 2>/dev/null | head -3 sudo ausearch -m avc -ts recent 2>/dev/null | tail -10
- Как исправить
-
Разметьте файлы нужным контекстом (
restorecon) или поправьте профиль AppArmor. Отключение модуля целиком — плохой способ решить точечную проблему.
- Почему происходит
- Параметры монтирования ro и noexec дают отказ при попытке записи или запуска, даже когда права разрешают.
- Как проверить
-
Посмотрите параметры монтирования нужного пути.
findmnt -T /var/lib/myapp -o TARGET,SOURCE,OPTIONS
- Как исправить
- Перемонтируйте раздел с нужными правами или перенесите данные туда, где запись разрешена. Раздел, ушедший в режим только для чтения сам, — признак ошибок файловой системы: проверьте записи ядра.
Пример вывода
Служба от пользователя app не может прочитать файл настроек, принадлежащий root. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
× myapp.service - My application
Active: failed (Result: exit-code) since Mon 2026-09-15 09:14:22 MSK; 2s ago
Process: 4410 ExecStart=/usr/local/bin/myapp --config /etc/myapp/config.yml (code=exited, status=1/FAILURE)
myapp[4410]: fatal: open /etc/myapp/config.yml: permission denied
systemd[1]: myapp.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: myapp.service: Failed with result 'exit-code'.
Частые вопросы
Права 777 решают проблему. Так можно оставить?
Работать будет, но это снимает симптом вместе с защитой: любой процесс на машине получит доступ к данным службы. Правильнее назначить владельцем пользователя службы и оставить права 750.
Почему от root всё работает, а служба получает отказ?
Потому что служба работает не от root, а от пользователя из User=. Проверяйте доступ через sudo -u с этим пользователем — картина сразу совпадёт с реальностью.
Связанные ошибки
- status=203/EXEC в systemd Код 203/EXEC означает, что systemd не смог выполнить программу из ExecStart=. Разбор причин: путь, права, интерпретатор, синтаксис оболочки.
- status=217/USER в systemd Код 217/USER означает, что systemd не смог определить или сменить пользователя из User=. Разбор причин: пользователя нет, имя недопустимо, конфликт с DynamicUser.
- status=226/NAMESPACE в systemd Код 226/NAMESPACE: не удалось настроить пространства имён монтирования, UTS или IPC. Частая причина — путь в ReadOnlyPaths= или ProtectHome=.
- Read-only file system в журнале службы Служба не может писать: файловая система только для чтения. Разбор: параметры изоляции unit, монтирование ro, ошибки файловой системы.
- status=209/STDOUT в systemd Код 209/STDOUT: systemd не смог настроить стандартный вывод службы. Чаще всего виноват путь в StandardOutput=append: или file:.
- MySQL: Can't open the mysql.plugin table и повреждение системных таблиц MySQL не запускается: недоступны или повреждены системные таблицы. Права на каталог данных, версия схемы, восстановление.
- No such file or directory в журнале службы Служба не находит файл или каталог. Разбор: путь, момент запуска, изоляция unit-файла, символические ссылки, приватный /tmp.
- Operation not permitted в журнале службы Операция запрещена: не хватает возможностей процесса, мешает seccomp или модуль безопасности. Отличие от Permission denied.
Где встречается чаще всего
Источники
-
systemd.exec(5)
User=, Group=, ProtectSystem=, ReadWritePaths= и их влияние на доступ. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено на файле root при User=app, на закрытом промежуточном каталоге и на ProtectSystem=strict.