Вопрос или проблема
У меня есть служба, работающая на RHEL9:
[Unit]
Description=Мое приложение
After=syslog.target network.target
[Service]
WorkingDirectory=/var/my/appname
ExecStart=java -Dlogging.config=/var/my/appname/myappname.logback.xml -jar /var/my/appname/myappname.jar /var/my/appname/myappname.gcptest.properties
ExecStop=/bin/kill 15 $MAINPID
Restart=on-failure
StandardOutput=file:/tmp/stdout.log
StandardError=file:/tmp/stderr.log
[Install]
WantedBy=multi-user.target
Это работает.
Но если я изменю StandardOutput/StandardError на file:/var/my/appname/logs/stdout.log
, служба не запускается:
(code=exited, status=209/STDOUT)
Очевидно, что есть какая-то проблема с правами доступа.
Файл службы находится в /etc/systemd/system
, поэтому он должен работать от имени root, так как я не указываю пользователя.
Директория /var/my/appname/logs
существует, и у нее, а также у всех родительских директорий в /var
, права root:root
drwxrw-rw-
. Сам /var
имеет права root:root
drwxr-xr-x
.
Я также пробовал просто записывать в /var/my/stdout.log
, но получал ту же проблему.
Может кто-нибудь подсказать, почему я не могу записать логи в свою поддиректорию /var?
–обновление–
aureport -a
показал, что это проблема с selinux; установка selinux в режим разрешения (setenforce 0
) позволила это сделать. Итак, как я могу дать соответствующие разрешения службе, не отключая SELinux?
Ответ или решение
Конечно! Давайте разберемся с вашей проблемой, связанной с записью вывода в файлы в директории /var/my/appname/logs
на системе RHEL9, учитывая, что это связано с SELinux.
Проблема:
Вы сталкиваетесь с ошибкой при запуске вашего Java-сервиса, когда указываете StandardOutput
и StandardError
так, чтобы они указывали на файлы в /var/my/appname/logs
. Более того, вы выяснили, что это связано с SELinux, который по умолчанию может блокировать попытки записи в определенные директории.
Решение:
Вместо отключения SELinux следует использовать правильные контексты безопасности, чтобы разрешить вашей службе доступ к необходимым ресурсам.
-
Проверьте контекст SELinux текущего каталога:
Вы можете проверить текущий контекст текущего каталогаlogs
, выполнив команду:ls -Z /var/my/appname/logs
-
Установите правильный контекст:
Вам нужно установить правильный контекст безопасности для этой директории, чтобы ваш Java-приложение могло записывать туда логи. Используйте следующую команду:sudo chcon -R -t var_log_t /var/my/appname/logs
Этот контекст (
var_log_t
) разрешает запись для ваших логов от системного процесса. -
Создание правила для постоянных изменений:
Изменение контекста с помощьюchcon
не будет постоянным, так как при следующей переустановке SELinux контекст может измениться. Для того чтобы установить это изменение как постоянное, создайте файл манифеста:sudo semanage fcontext -a -t var_log_t "/var/my/appname/logs(/.*)?"
Затем примените изменения:
sudo restorecon -R /var/my/appname/logs
-
Перезагрузите службу:
После изменения контекста попробуйте снова перезапустить ваш сервис:sudo systemctl daemon-reload sudo systemctl start your-service-name
Замените
your-service-name
на имя вашего сервиса. -
Проверка состояния службы:
Убедитесь, что служба работает корректно:systemctl status your-service-name
Заключение:
Теперь ваш Java-сервис должен быть способен записывать логи в файлы в директории /var/my/appname/logs
, без необходимости отключать SELinux. Это подход более безопасный и соответствующий рекомендованным практикам.
Если у вас возникнут дополнительные вопросы или проблемы, не стесняйтесь задавать!