systemd服务单元文件中的动态变量


14

有没有办法在systemd服务单元文件中动态分配环境变量?

我们有一台具有4个GPU的机器,并且我们希望每个GPU加速某个服务的多个实例。例如:

  • gpu_service @ 1:1.service
  • gpu_service @ 2:1.service
  • gpu_service @ 3:1.service
  • gpu_service @ 4:1.service
  • gpu_service @ 1:2.service
  • gpu_service @ 2:2.service
  • gpu_service @ 3:2.service
  • gpu_service @ 4:2.service
  • 广告恶心

因此,1:1、2:1等实际上是服务单元文件中的%i。

为了使服务绑定到特定的GPU,服务可执行文件检查某个环境变量,例如:

USE_GPU=4

有没有一种方法可以将%i放入服务单元文件中,并通过某些(外壳)函数运行它以得出GPU编号,然后可以相应地设置USE_GPU环境变量?

最重要的是,我不想/etc/systemd/system/gpu_service@x:y.service/local.conf只写多个文件的麻烦,这样我就可以启动更多实例。

Answers:


10

如果您小心一点,可以将一个小的bash脚本序列作为exec命令并入实例服务文件中。例如

ExecStart=/bin/bash -c 'v=%i; USE_GPU=$${v%:*} exec /bin/mycommand'

$$字符串中的in将$在传递给bash的结果中成为单个,但更重要的是,将不再${...}被systemd插值。(systemd的早期版本未记录的使用$$,因此我不知道当时是否受支持)。


我最终做了这样的事情。:)
Kal

1
调用a bash -c从单位文件启动程序?打电话exec?这就像在叉车的顶部使用叉车(也许在顶部使用另一个叉车)一样,因为第一个叉车实际上在叉车方面遇到了麻烦。
David Tonhofer

不幸的是,您不能使用ExecStartPre来编写一个env文件,然后再使用它,显然必须事先编写它,这样就可以了。或使用包装脚本执行拆分:)另一个奇怪的选择是创建另一个服务来设置环境。文件,不确定如何使用模板,例如:stackoverflow.com/a/42841480/32453
rogerdpack

8

没有内置的方式。您需要在开始服务之前执行这些操作。一种方法是将其放入环境文件。

[Service]
# Note you need to escape percentage sign
ExecStartPre=/bin/sh -c "my_awesome_parser %%i > /run/gpu_service_%i"
EnvironmentFile=/run/gpu_service_%i
ExecStart=...

4

看来您确实可以在systemd单位文件中设置环境变量。

根据评论者的建议,以下是解决方案:

以系统单位使用环境变量

环境指令

systemd具有环境指令,该指令为执行的进程设置环境变量。它采用以空格分隔的变量分配列表。可以多次指定此选项,在这种情况下,将设置所有列出的变量。如果同一变量设置两次,则后面的设置将覆盖前面的设置。如果将空字符串分配给此选项,则将重置环境变量列表,所有先前的分配均无效。Environments指令在内置的Container Linux系统单元中使用,例如在etcd2和法兰绒中。

在下面的示例中,您可以将etcd2守护程序配置为使用加密。只需/etc/systemd/system/etcd2.service.d/30-certificates.conf为etcd2.service 创建插件:

[Service]
# Client Env Vars
Environment=ETCD_CA_FILE=/path/to/CA.pem
Environment=ETCD_CERT_FILE=/path/to/server.crt
Environment=ETCD_KEY_FILE=/path/to/server.key
# Peer Env Vars
Environment=ETCD_PEER_CA_FILE=/path/to/CA.pem
Environment=ETCD_PEER_CERT_FILE=/path/to/peers.crt
Environment=ETCD_PEER_KEY_FILE=/path/to/peers.key

然后运行sudo systemctl daemon-reload并将sudo systemctl restart etcd2.service新环境应用于etcd2守护程序。

引用的文本摘自以下URL:https : //coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html


2
虽然从理论上讲这可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。
斯蒂芬·劳奇

1
虽然您的评论从理论上可能会改善我将来在stackexchange上的反应,但最好将答案的基本内容包括在您的评论中,而不是仅仅评论指出某人的能力如何:)
Cyber​​K

1
欢迎使用Stack Exchange!感谢您的评论,您让我微笑。也感谢您抽出宝贵的时间来编辑答案。我们正在尝试构建一些随着时间的推移会有价值的东西,并且仅链接答案就不会很好地老化。
Stephen Rauch

如果添加Environment=ABC=%i它,则会设置该环境。变量“整个%i”。我想您可以做一个包装程序,以剥离不需要的“超出引号的内容”,它会调用真正的可执行文件。但是,如果要制作包装纸,甚至可以将其%i作为参数传递给ex:ExecStart=my_wrapper %i
rogerdpack,

0

这很丑陋,而且不完全符合您的要求,也不允许自动启动,但是对于追随者来说,可以使用systemctl 环境进行某些操作:

$ sudo systemctl set-environment USE_GPU=4 # add it to the env. variables for future services
$ sudo systemctl start gpu_service@4:2.service

只是试图列出所有可能的方法:)

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.