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

Kal*_*Kal 21 configuration systemd services

有没有办法在 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
Run Code Online (Sandbox Code Playgroud)

有没有办法在服务单元文件中获取 %i 并通过一些(shell)函数运行它来导出 GPU 编号,然后我可以相应地设置 USE_GPU 环境变量?

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

meu*_*euh 17

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

ExecStart=/bin/bash -c 'v=%i; USE_GPU=$${v%:*} exec /bin/mycommand'
Run Code Online (Sandbox Code Playgroud)

$$字符串中的in 将$在传递给 bash 的结果中变为单个,但更重要的是将停止${...}被 systemd 插入。(早期版本的 systemd 没有记录 的使用$$,所以我不知道当时是否支持)。

  • 调用`bash -c` 从单元文件启动程序?调用`exec`?这就像在叉车顶部使用叉车(可能在顶部有另一辆叉车),因为第一辆叉车在实际叉车时遇到了麻烦。 (8认同)
  • @DavidTonhofer 没有“双叉车”的解决方案会是什么样子?我看到 bash 是用来设置和修改 `%i` 为 `USE_GPU` 的。然后 exec 将 shell 进程替换为真正的进程。 (2认同)

小智 9

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

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

  • 不幸的是,您不能使用 ExecStartPre 编写 env 文件,然后使用它,显然它必须事先编写。 (3认同)