我有一个带有 systemd 的 Arch Linux 系统我已经创建了自己的服务。配置服务/etc/systemd/system/myservice.service
如下所示:
[Unit]
Description=My Daemon
[Service]
ExecStart=/bin/myforegroundcmd
[Install]
WantedBy=multi-user.target
现在我想为设置环境变量/bin/myforegroundcmd
。我该怎么做?
答案1
时代在变,最佳实践也在变。
这当前的最好的方法是运行systemctl edit myservice
,它将为您创建一个覆盖文件或让您编辑现有文件。
在正常安装中,这将创建一个目录/etc/systemd/system/myservice.service.d
,并在该目录内创建一个名称以 结尾的文件.conf
(通常为override.conf
),并且您可以在此文件中添加或覆盖发行版附带的任何单元。
例如,在文件中/etc/systemd/system/myservice.service.d/myenv.conf
:
[Service]
Environment="SECRET=pGNqduRFkB4K9C2vijOmUDa2kPtUhArN"
Environment="ANOTHER_SECRET=JP8YLOc2bsNlrGuD6LVTq7L36obpjzxd"
还请注意,如果目录存在且为空,您的服务将被禁用!如果您不打算将某些内容放入目录中,请确保它不存在。
作为参考,旧方法是:
推荐方法要做到这一点,就是创建一个/etc/sysconfig/myservice
包含变量的文件,然后用加载它们EnvironmentFile
。
有关完整详细信息,请参阅 Fedora 的文档如何编写 systemd 脚本。
答案2
答案取决于变量是否应该是常量(即,不应该由用户获取单位来修改)还是变量(应该由用户设置)。
由于它是您的本地单位,因此边界非常模糊,无论哪种方式都可以。但是,如果您开始分发它并且它最终会变成/usr/lib/systemd/system
,那么这一点就变得很重要。
常数值
如果该值不需要根据每个实例进行更改,则首选方法是将其Environment=
直接放置在单元文件中:
[Unit]
Description=My Daemon
[Service]
Environment="FOO=bar baz"
ExecStart=/bin/myforegroundcmd
[Install]
WantedBy=multi-user.target
这样做的好处是变量与单元保存在同一个文件中。因此,单元文件更容易在系统之间移动。
变量值
但是,当系统管理员需要在本地更改环境变量的值时,上述解决方案效果不佳。更具体地说,每次更新单元文件时都需要设置新值。
对于这种情况,需要使用额外的文件。如何使用 — 通常取决于分发策略。
一个特别有趣的解决方案是使用/etc/systemd/system/myservice.service.d
目录。与其他解决方案不同,此目录由 systemd 本身支持,因此不附带特定于发行版的路径。
在这种情况下,您可以放置一个类似的文件/etc/systemd/system/myservice.service.d/local.conf
来添加单元文件缺失的部分:
[Service]
Environment="FOO=bar baz"
之后,systemd 在启动服务时会合并这两个文件(记住systemctl daemon-reload
在更改其中任何一个文件后合并)。由于此路径由 systemd 直接使用,因此您无需使用EnvironmentFile=
它。
如果仅需要在某些受影响的系统上更改该值,则可以结合两种解决方案,在单元中直接提供默认值,并在另一个文件中提供本地覆盖。
答案3
答案来自迈克尔和米哈乌很有帮助,并回答了如何为 systemd 服务设置环境变量的原始问题。然而,共同使用环境变量是在不会意外地与应用程序代码一起提交到源代码控制的地方配置密码等敏感数据。
如果这就是你想要将环境变量传递给服务的原因,不要Environment=
在单元配置文件中使用。使用EnvironmentFile=
并将其指向仅服务帐户(和具有 root 访问权限的用户)可读的另一个配置文件。
任何用户都可以通过以下命令查看单元配置文件的详细信息:
systemctl show my_service
我放置了一个配置文件/etc/my_service/my_service.conf
并将我的秘密放在其中:
MY_SECRET=correcthorsebatterystaple
STARFLEET_SECRET=412Mark80
然后在我的服务单元文件中,我使用EnvironmentFile=
:
[Unit]
Description=my_service
[Service]
ExecStart=/usr/bin/python /path/to/my_service.py
EnvironmentFile=/etc/my_service/my_service.conf
User=myservice
[Install]
WantedBy=multi-user.target
我检查过,ps auxe
看不到这些环境变量,其他用户无权访问/proc/*/environ
。当然,请检查您自己的系统。
答案4
Michael 给出了一个干净的解决方案,但我想从脚本中获取更新的环境变量。不幸的是,在 systemd 单元文件中无法执行 bash 命令。幸运的是,您可以在 ExecStart 中触发 bash:
http://www.dsm.fordham.edu/cgi-bin/man-cgi.pl?topic=systemd.service§=5
请注意,此设置不直接支持 shell 命令行。如果要使用 shell 命令行,则需要将其明确传递给某种 shell 实现。
我们的例子中的例子是:
[Service]
ExecStart=/bin/bash -c "ENV=`script`; /bin/myforegroundcmd"