使用环境设置的可执行路径编写 systemd 单元文件

Rob*_*anu 17 java systemd

我正在为 Java 应用程序编写 systemd 单元文件,我想控制用于启动它的 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
Run Code Online (Sandbox Code Playgroud)

尝试启动时,我收到错误消息

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.
Run Code Online (Sandbox Code Playgroud)

我知道JAVA_HOME设置正确;如果我改变ExecStart行开始,/usr/bin/java然后添加一些-DsomeOption=${JAVA_HOME}我可以看到的东西就好了。

显而易见的解决方法是创建一个包装脚本,但我觉得它违背了使用服务文件的意义。

如何使用单元文件为我的 Java 应用程序设置 JAVA_HOME?

Wie*_*and 12

从 systemd.service(5) 中的“命令行”部分:

请注意,第一个参数(即要执行的程序)可能不是变量。

我打算建议使用实例说明符%i(您可以在 systemd.unit(5) 中阅读有关它的更多信息),但是(现在我们又回到了 systemd.service(5) 中):

命令行的第一个参数(即要执行的程序)可能不包含说明符。

我认为此时最好的选择确实是创建一个 shell 脚本,它按照 Warren Young 的建议包装 java 二进制文件的执行,或者您可以像在“命令行”部分中的 shell 命令行示例中一样直接 ExecStart 一个 shell systemd.service(5) 具有以下示例:

ExecStart=/bin/sh -c 'dmesg | tac'
Run Code Online (Sandbox Code Playgroud)

所以你可以这样做(未经测试):

ExecStart=/bin/sh -c '${JAVA_HOME}....'
Run Code Online (Sandbox Code Playgroud)