从单元文件内的命令行设置环境变量

zoz*_*015 5 environment-variables systemd systemctl

我正在尝试在单元文件中设置一个日期以进行记录

我的单元文件如下所示:

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

设置日期并不能正常工作。我得到的错误如下:

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

知道如何配置它才能工作吗?

fil*_*den 8

ExecStart=systemd 服务单元中的命令并不真正在 shell 上运行,因此 shell 扩展(例如$(...)您在那里使用的命令替换)实际上并不可用。

您可以通过显式调用 shell 脚本来使用它们/bin/sh -c '...',在您的ExecStartPre=. 例如:

ExecStartPre=/bin/sh -c 'systemctl set-environment date=$$(/bin/date +%%Y-%%m-%%d-%%H-%%M)'
Run Code Online (Sandbox Code Playgroud)

请注意,您需要使用 来转义$自身,$$否则 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 ...
Run Code Online (Sandbox Code Playgroud)

再次注意,转义$with $${date},因此 systemd 不认为它是要扩展的 systemd 变量。此外,exec用于确保 shell 被java进程替换,确保 systemd 知道服务的主要 PID 是什么。

在 systemd 上转义ExecStart=很快就会变得复杂和繁重......所以考虑将 shell 脚本存储在一个文件中(在这种情况下,您无需担心转义$以及%引号的工作方式可能会略有不同)并运行来自 的脚本ExecStart=,这要简单得多(即使它需要一个额外的文件......)