这是一个常见的 Upstart 问题,但让我用一个具体案例来说明:
Centrify 是 NIS 到 ActiveDirectory 的网关。它需要在任何依赖其提供的身份验证服务的服务之前加载,例如 autofs、cron、nis 等。
事实证明,这是相当具有挑战性的,即使试图改变其他服务的依赖关系(无论如何我认为我们不应该这样做,如果可能的话,我不想触碰其他 Upstart 工作)。
有什么建议吗?
答案1
解决方案是从另一个方向解决问题:为了满足 Centrify 的启动标准,不需要让现有服务依赖于新的 Centrify 服务,而是让新的 Centrify 服务依赖于现有服务。
例如,Upstart 配置文件/etc/init/centrify.conf
可以这样写:
启动于(启动 cron 或启动 autofs 或启动 nis)
将其转换成英语,翻译如下:
启动 Centrify 服务就在之前cron、autofs 或 nis 启动 (以先启动者为准)。
cron、autofs 或 nis 的启动顺序无关紧要:Upstart 将确保 Centrify 在首先启动的服务之前启动,从而确保 Centrify 在任何一项服务启动之前运行。
还要注意,Upstart 将阻止第一个想要启动的服务的启动,直到 Centrify 开始运行。
一旦你习惯了这种思考方式就会非常优雅和简单。
答案2
James 的答案适用于 1 对 1 依赖关系。对于 1 对多依赖关系,即要确保服务 A 在服务 B、C 和 D 之前启动,您需要采取另一种方法。您可以查看当前的 portmap 脚本以供参考,但以下是一般方法:创建等待脚本。
场景:你希望服务 A总是在 service-b、service-c 和服务-d 之前运行。
解决方案:为服务 A 创建一个等待脚本。将其命名为“/etc/init/service-a-wait.conf”
# service-a-wait
start on (starting service-b
or starting service-c
or starting service-d)
stop on (started service-a or stopped service-a)
# We know that we have more than one job that needs to wait for service-a and
# will make use of this service, so we need to instantiate.
instance $JOB
# Needed to make starting the job successful despite being killed
normal exit 2
task
script
status service-a | grep -q "start/running" && exit 0
start service-a || true
# Waiting forever is ok.. upstart will kill this job when
# the service-a we tried to start above either starts or stops
while sleep 3600 ; do :; done
end script
用简单的英语来说,这意味着:当服务 b、c 或 d 发出要启动的信号时,它们必须等到服务 a 运行后才能启动。服务 a-wait 作业旨在运行到服务 a 启动为止。一旦服务 a-wait 退出,服务 b、c 和 d 就可以继续运行。
这将确保服务 a 在其任何反向依赖项尝试启动之前启动并运行。
注意:在这种“开始于...或...或...”的场景中,“实例 $JOB”行非常重要。否则,您实际上只会阻止 B、C 或 D 中先触发的那个。
(老实说,实例化值得更好的解释。现在,就这么做吧。;)