Запись файла системного модуля с заданным в среде путем к исполняемому файлу

17

Я пишу системный файл модуля для приложения Java, и я хотел бы контролировать версию Java, используемую для его запуска. Мой (упрощенный) сервисный файл

[Service]
Type=simple
EnvironmentFile=%h/Documents/apps/app/app-%i/app.cfg
ExecStart=${JAVA_HOME}/bin/java ${JAVA_OPTS} -jar %h/Documents/apps/app/app-%i/myapp.jar
SuccessExitStatus=143

При попытке запустить получаю ошибку обратно

Apr 28 12:43:37 rombert systemd[1613]: [/home/robert/.config/systemd/user/app@.service:7] Executable path is not absolute, ignoring: ${JAVA_HOME}/bin/java ${JAVA_OPT
Apr 28 12:43:37 rombert systemd[1613]: app@1.0.0.service lacks both ExecStart= and ExecStop= setting. Refusing.

Я знаю, что JAVA_HOMEэто правильно установлено; если я изменю ExecStartстроку, чтобы начать с, /usr/bin/javaа затем добавить что-то вроде, -DsomeOption=${JAVA_HOME}я вижу это просто отлично.

Очевидный обходной путь заключается в создании сценария-обертки, но я чувствую, что он лишает смысла использование служебного файла.

Как я могу установить JAVA_HOME для моего Java-приложения, используя файл модуля?

Роберт Мунтяну
источник
Почему скрипт-оболочка не позволяет точно использовать сервисный файл? Вы по-прежнему получаете последовательности systemd и отслеживание зависимостей, мониторинг и т. Д. По сути, systemd заменяет программируемость в свободной форме, которую мы имели с SysVinit, в пользу встроенной логики DTRT . Когда «правильная вещь» - это то, что systemd не делает, вам нужно поместить это вне systemd, как в сценарии оболочки.
Уоррен Янг
@WarrenYoung - потому что я неожиданно снова начинаю управлять скриптами оболочки. В моем случае неуправление сценарием оболочки более полезно, чем другие биты.
Роберт Мунтяну
Я действительно не вижу проблемы. Вы проводите свои дни, заботясь обо всех исполняемых файлах, которыми вы тоже должны управлять? :)
Уоррен Янг
3
Из systemd.service (5): «Обратите внимание, что первый аргумент (т.е. программа для выполнения) не может быть переменной». Это объясняет, почему $ {JAVA_HOME} не раскрывается в начале пути приложения, а используется при более позднем этапе.
Виланд
@WarrenYoung - я предпочитаю одну оболочку над двоичным. Я понимаю, что это не проблема для всех, но это для меня :-)
Роберт Мунтяну

Ответы:

12

Из раздела «Командные строки» в systemd.service (5):

Обратите внимание, что первый аргумент (т.е. программа для выполнения) может не быть переменной.

Я собирался предложить использовать спецификатор экземпляра %i(вы можете прочитать об этом больше в systemd.unit (5)), но (теперь мы вернулись в systemd.service (5)):

первый аргумент командной строки (т.е. программа для выполнения) может не включать спецификаторы.

Я думаю, что на данный момент лучшим вариантом на самом деле является создание сценария оболочки, который оборачивает выполнение двоичного файла Java, как это было предложено Уорреном Янгом, или вы можете напрямую выполнить ExecStart оболочку, как в примере для командных строк оболочки в разделе «Командные строки» systemd.service (5), который имеет следующий пример:

ExecStart=/bin/sh -c 'dmesg | tac'

так что вы могли бы сделать (не проверено):

ExecStart=/bin/sh -c '${JAVA_HOME}....'
Wieland
источник
2

Еще один аналогичный вариант заключается в использовании /usr/bin/env:

ExecStart=/usr/bin/env "${JAVA_HOME}/bin/java" -jar ...

Таким образом, вы можете опускать 'кавычки вокруг всей команды, что полезно, если вам нужно вложить кавычки.

PS. В качестве дополнительного примечания важно заключить имена переменных в {фигурные скобки }в файлы Systemd, иначе они не будут распознаваться правильно.

MarSoft
источник