systemctl перенаправляет stdout/stderr сервиса Java в файлы в /var/my/appname/logs

Вопрос или проблема

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

  1. Проверьте контекст SELinux текущего каталога:
    Вы можете проверить текущий контекст текущего каталога logs, выполнив команду:

    ls -Z /var/my/appname/logs
  2. Установите правильный контекст:
    Вам нужно установить правильный контекст безопасности для этой директории, чтобы ваш Java-приложение могло записывать туда логи. Используйте следующую команду:

    sudo chcon -R -t var_log_t /var/my/appname/logs

    Этот контекст (var_log_t) разрешает запись для ваших логов от системного процесса.

  3. Создание правила для постоянных изменений:
    Изменение контекста с помощью chcon не будет постоянным, так как при следующей переустановке SELinux контекст может измениться. Для того чтобы установить это изменение как постоянное, создайте файл манифеста:

    sudo semanage fcontext -a -t var_log_t "/var/my/appname/logs(/.*)?"

    Затем примените изменения:

    sudo restorecon -R /var/my/appname/logs
  4. Перезагрузите службу:
    После изменения контекста попробуйте снова перезапустить ваш сервис:

    sudo systemctl daemon-reload
    sudo systemctl start your-service-name

    Замените your-service-name на имя вашего сервиса.

  5. Проверка состояния службы:
    Убедитесь, что служба работает корректно:

    systemctl status your-service-name

Заключение:

Теперь ваш Java-сервис должен быть способен записывать логи в файлы в директории /var/my/appname/logs, без необходимости отключать SELinux. Это подход более безопасный и соответствующий рекомендованным практикам.

Если у вас возникнут дополнительные вопросы или проблемы, не стесняйтесь задавать!

Оцените материал
Добавить комментарий

Капча загружается...