抽象的例子:
我有两个重复任务A
,B
我想将其设置为systemd
服务。由于任务彼此非常相似,因此我使用模板[email protected]
; A 和 B 将分别作为该模板的实例运行:[email protected]
和[email protected]
。
# [email protected]
[Unit]
Description= myservice %I
[Service]
Type=oneshot
IOSchedulingClass=idle
ExecStart=bash -c "echo Starting %I; sleep 10; echo Finished %I"
Restart=on-failure
这两个任务的重复要求应通过两个计时器myservice-A.timer
和来处理myservice-B.timer
。计时器将确保根据配置的时间间隔重复这两个任务,例如A
每周和B
每天。即使在当时 PC 关闭的情况下,计时器也能保证这一点,在这种情况下,当超过预先配置的重新启动时间时,它们将尽快启动服务。
A
然而,最后一种情况可能与之前必须完成的要求相冲突B
(如果两者同时启动)。由于我使用的是模板实例,因此我无法在服务本身上使用Before=
和选项。After=
我可以将它们添加到计时器中,但这似乎并不能解决问题(可能是因为现在计时器只获得排序依赖项,而不是它们正在启动的服务)。
# myservice-A.timer
[Unit]
# The Before= requirement below does not help
Before=myservice-B.timer
Description=weekly execution of myservice
[Timer]
OnCalendar=Monday *-*-* 09:20:00
Persistent=true
[email protected]
[Install]
WantedBy=timers.target
# myservice-B.timer
[Unit]
# the After= requirement below does not help
After=myservice-A.timer
Description=daily execution of myservice
[Timer]
OnCalendar=09:30:00
Persistent=true
[email protected]
[Install]
WantedBy=timers.target
请注意,B
不需要执行A
,即我不寻找类型的依赖项Requires=
。我只讨论这样的情况:当 和 都A
通过B
计时器启动时,thenA
必须在B
启动之前完成。
答案1
由于我使用的是模板实例,因此我无法使用服务本身的
Before=
和选项。After=
但是,您可以在模板的特定实例上设置这些。然而,为了使任何一种关系都能很好地发挥作用,注意:
最重要的是,对于服务单元来说,
Before=
当After=
所有配置的启动命令都已被调用并且它们失败或报告启动成功时,启动被视为已完成。
也就是说,[email protected]
一旦ExecStart
命令开始执行。它不会等待它完成。但是,如果您在ExecStartPre
命令中执行这些单元的实际工作,并且可能只使用简单的/bin/true
for ExecStart
,那么排序应该有效。也许像这样:
# [email protected]
[Unit]
Description= myservice %I
[email protected] # Will be skipped for `myservice@A` itself
[Service]
Type=oneshot
IOSchedulingClass=idle
ExecStartPre=/bin/bash -c "echo Starting %I; sleep 10; echo Finished %I"
ExecStart=/bin/true
Restart=on-failure
如果您的命令需要很长时间才能执行,您可能需要配置 setTimeoutStartSec
因此。