如何编写保证运行的 Upstart 任务只有一次每次启动后,但也能保证在至少两个其他作业之一开始运行之前完成运行。我不想更改这两个其他作业的 Upstart 初始化文件,因为它们不属于我。重新启动这两个其他作业中的任何一个都不应导致所需任务再次运行。
情况是,所需任务必须对本地文件系统中的其他两个作业都需要的某些文件进行一些修改。
我对 Upstart 还很陌生,学习难度比我想象的要大,因此为什么解决方案的效果与解决方案本身一样有价值。
答案1
我相信我有一个答案可以解决我自己的问题CameronNemo 的部分解决方案和马克·拉塞尔的回答回答一个相关但略有不同的问题。
需要两个 Upstart 配置文件。第一个是本地文件系统可用时立即启动的作业,作为预启动脚本执行所需的文件修改,然后永远处于运行状态:
# modify-files - Single-execution file modification job
start on local-filesystems
console log
pre-start script
echo "$(date --rfc-3339=ns) $(hostname) $UPSTART_JOB"
exec /path/to/your/script
end script
第二个配置文件是一个 Upstart 任务,它延迟所有可能依赖于我们尝试修改的文件的其他作业的启动。它为每个依赖的作业生成一个实例:
# modify-files-wait - Helper task for modify-files
start on (starting jobA or jobB)
stop on (started modify-files or stopped modify-files)
instance $JOB
console log
normal exit 0 2
task
script
echo "$(date --rfc-3339=ns) $(hostname) $UPSTART_JOB ($UPSTART_INSTANCE)"
status modify-files | grep -q "start/running" && exit 0
start modify-files || true
sleep infinity
end script
modify-files-wait
一旦modify-files
处于运行状态,Upstart 将终止所有处于空闲状态的 实例。该normal exit
行解释了在其无限休眠期间被终止的可能性。我们需要该行task
来阻止 jobA 和 joB,直到达到停止状态。无论哪个实例先运行,都将启动 (modify-files
如果它尚未启动)。
由于modify-files
永远不会达到停止状态,因此无论作业 A 还是作业 B 是否重新启动,它都不会重新运行。
这个解决方案似乎有效,但我欢迎任何批评或改进。
答案2
您可以定义一个简单的任务作业,该作业在您选择的事件时启动,运行您的脚本,并在最后发出事件来启动另外两个作业。
例如:
# mainJob -
#
# This service emit myEvent to run firstJob
description "emit myEvent to run firstJob"
start on runlevel [2345]
task
console log
script
echo "(startTask) $UPSTART_JOB -- $UPSTART_EVENTS"
exec /path/to/your/script
initctl emit -n myEvent
end script
为了不修改其他两个作业的 upstart 脚本,你应该覆盖文件您可以通过修改启动和停止条件来修改作业启动和停止的方式。
按照我的例子,我创建了一个简单的firstJob.conf
如下:
# firstJob -
#
# This service print environment variable
description "print environment variable"
start on runlevel [2345]
stop on runlevel [016]
task
console log
script
if [ "$RUNLEVEL" = "0" -o "$RUNLEVEL" = "1" -o "$RUNLEVEL" = "6" ]; then
exec echo "(stopTask) $UPSTART_JOB -- $UPSTART_EVENTS"
else
exec echo "(startTask) $UPSTART_JOB -- $UPSTART_EVENTS"
fi
end script
然后我覆盖在创建覆盖文件的条件下开始:
echo "start on myEvent" > /etc/init/firstJob.override
因此将从生成firstJob
开始并停止于myEvent
mainJob
runlevel [016]
我在 lubuntu 12.04 上测试了这些作业,重启后我发现/var/log/upstart/firstJob.log
:
(startTask) firstJob -- myEvent
您应该检查“其他两个作业”是否需要特定的事件条件才能启动,并确保mainJob
在这些事件上启动。
答案3
start on starting jobA or starting jobB
instance $JOB
pre-start exec /path/to/script
起始位会阻止作业在其生命周期中继续进行,直到该作业完成为止。
实例位使得两个启动事件(针对 jobA 和 jobB)都受到抑制,而不仅仅是一个,就像没有实例节的情况一样。
使用预启动 exec/script(代替常规 exec/script)是为了当脚本/执行的命令完成时,该作业仍将被视为正在运行,而使用传统的 exec/script,当 exec/script 退出时,该作业被视为停止。
使用任务将会使得作业运行两次(例如,如果您重新启动作业),因此我们将其排除在外。