我正在尝试在单元文件中设置一个日期以进行记录
我的单元文件如下所示:
[Unit]
Description=Jetty service
After=multiuser.target
[Service]
Environment=MAIN_CLASS="com.candorgrc.nphase.MainJetty"
Type=simple
User=jetty
Group=jetty
WorkingDirectory=/home/jetty/dist
PermissionsStartOnly=true
ExecStartPre=/bin/systemctl set-environment date=$(/bin/date +%%Y-%%m-%%d-%%H-%%M)
ExecStart=/usr/bin/java -Xms512m -Xmx1024m -Djava.util.logging.config.file=/home/jetty/logging.properties -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/u01/jetty/hdumps/hdump_${date} -verbose:gc -Dcom.sun.management.jmxremote.port=12321 -Dcom.sun.management.jmxremote.authen
PIDFile=/var/run/jetty.pid
ExecReload=/bin/kill -HUP $MAINPID
#Restart=on-failure
ExecStop=/bin/kill -9 $MAINPID
设置日期似乎不起作用。我收到的错误如下:
Nov 26 16:47:50 vps203756 systemctl[14275]: Failed to set environment: Invalid environment assignments
Nov 26 16:47:50 vps203756 systemd[1]: jetty.service: Control process exited, code=exited status=1
Nov 26 16:47:50 vps203756 systemd[1]: jetty.service: Failed with result 'exit-code'.
Nov 26 16:47:50 vps203756 systemd[1]: Failed to start Jetty service.
知道如何配置它才能使其工作吗?
答案1
systemd 服务单元中的命令ExecStart=
实际上并不在 shell 上运行,因此 shell 扩展(例如$(...)
您在那里使用的命令替换)实际上不可用。
/bin/sh -c '...'
您可以通过在 中显式调用 shell 脚本来使用它们ExecStartPre=
。例如:
ExecStartPre=/bin/sh -c 'systemctl set-environment date=$$(/bin/date +%%Y-%%m-%%d-%%H-%%M)'
请注意,您需要$
使用 来转义 本身$$
,否则 systemd 将尝试将其解释为 systemd 变量扩展。(实际上,由于下一个字符是(
,因此单个字符$
可能有效,但将其加倍是更正确的设置。)
请注意,systemctl set-environment
不建议使用你正在做的方式,因为你正在创建一个全球的环境变量${date}
在任何地方都可用。
相反,考虑ExecStart=
通过 shell 运行你的命令,在这种情况下,你可以定义一个 shell 变量${date}
并只在你需要它的地方使用它:
ExecStart=/bin/sh -c 'date=$$(/bin/date +%%Y-%%m-%%d-%%H-%%M); exec java -Xms512m -Xmx1024m ... -XX:HeapDumpPath=/u01/jetty/hdumps/hdump_$${date} -verbose:gc ...
再次注意,使用 进行转义$
,$${date}
这样 systemd 就不会认为它是需要扩展的 systemd 变量。此外,使用exec
确保 shell 被替换为进程java
,确保 systemd 知道服务的主 PID 是什么。
在 systemd 上转义ExecStart=
很快就会变得复杂和繁重...因此,考虑将 shell 脚本存储在文件中(在这种情况下,您不必担心转义$
和%
引号的工作方式略有不同)并直接从 运行该脚本ExecStart=
,这样简单得多(即使它需要一个额外的文件......)