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


17

我正在为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

尝试启动时,出现错误提示

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应用程序设置JAVA_HOME?


包装器脚本为什么会完全违反使用服务文件的目的?您仍然可以获得systemd的排序和相关性跟踪,监视等。基本上,systemd会舍弃 SysVinit拥有的自由格式可编程性,而采用内置的DTRT逻辑。当“正确的事情”是systemd不能做的事情时,您需要将其放在systemd外部,例如在shell脚本中。
沃伦·杨

@WarrenYoung-因为我突然开始再次管理shell脚本。就我而言,不管理shell脚本比其他功能更有用。
罗伯特·蒙提亚努

我真的没看到问题。您是否整日都在担心必须管理的所有可执行文件?:)
沃伦·杨

3
来自systemd.service(5):“请注意,第一个参数(即要执行的程序)可能不是变量。” 这就解释了为什么$ {JAVA_HOME}不在应用程序路径的开头扩展,而是在以后的某个位置使用。
维兰德

@WarrenYoung-与二进制文件相比,我更喜欢使用单个包装器。我知道这不是每个人的问题,但这对我来说是:-)
Robert Munteanu 2015年

Answers:


12

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

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

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

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

我认为目前最好的选择是按照Warren Young的建议创建一个封装Java二进制代码执行的shell脚本,或者您可以像下面的“命令行”部分中的shell命令行示例一样直接执行ExecStart shell。 systemd.service(5)具有以下示例:

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

因此,您可以做(未试用):

ExecStart=/bin/sh -c '${JAVA_HOME}....'

2

另一个类似的选择是使用 /usr/bin/env

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

这样,您可以'在整个命令中省略引号,如果您需要嵌套引用的内容,这很有用。

PS。附带说明,将变量名称用{大括号括}在Systemd文件中非常重要,否则它们将无法正确识别。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.