我有多个 systemd 服务需要生成的环境文件。我有一个生成此环境文件的 shell 脚本,但因为我需要该环境文件前执行任何 Exec... 命令,我无法使用 ExecStartPre=generate_env_file.sh 。因此,我设置了另一个服务(generate_env_file.service)来一次性运行该脚本:
[Service]
Type=oneshot
ExecStartPre=/usr/bin/touch /path/to/config.ini
ExecStart=/path/to/generate_env_file.sh
我还有多个其他服务文件,其中包含:
[Unit]
Requires=generate_env_file.service
After=generate_env_file.service
如何保证两个或多个依赖服务(需要generate_env_file.service)不会并行运行并生成两个并行执行的generate_env_file.service?
我已经考虑过使用 RemainAfterExit=true 或可能的 StartLimitIntervalSec= 和 StartLimitBurst= 来确保在一段时间内一次只会执行一个副本,但我不确定执行此操作的最佳方法。
答案1
RemainAfterExit=true
是要走的路。在这种情况下,Systemd 启动服务,并且 Systemd 认为它已启动并处于活动状态。然而,这并不涵盖执行的用例systemctl restart generate_env_file.service
。在这种情况下,systemd 将重新执行您的服务。为了解决这个问题,您可以在运行文件系统中创建一个标记文件ExecStartPost=
并添加ConditionPathExists=
指令检查文件是否存在。
答案2
ConditionFirstBoot
可能也很有趣:
采用布尔参数。该条件可用于根据系统是否第一次启动来确定单元的条件。这大致意味着
/etc/
系统开始启动时未填充(有关详细信息,请参阅《首次启动语义》 机器 ID(5))。管理器完成启动阶段后,首次启动被视为已完成(此条件将评估为 false)。此条件可用于
/etc/
在恢复出厂设置后首次启动时填充,或者在新系统实例首次启动时填充。为了鲁棒性,单位
ConditionFirstBoot=yes
应该先命令自己first-boot-complete.target
并用 拉入这个被动目标Wants=
。这确保了在首次启动中止的情况下,这些单元将在下次系统启动期间重新运行。如果
systemd.condition-first-boot=
在内核命令行上指定了该选项(采用布尔值),它将覆盖此条件检查的结果,优先于/etc/machine-id
存在检查。
答案3
更新generate_env_file.sh
以在启动后立即检查锁定文件是否存在。如果锁定文件存在,则立即退出。
如果不存在锁定文件,请立即触摸锁定文件,然后执行生成配置文件的操作,然后删除锁定文件。
换句话说,我认为没有systemd
一种本机方法可以处理您通过配置描述的情况,因此请使用锁定文件。
正如 @shellter 指出的那样,Unix 站点是一个更适合systemd
将来提问的站点。