我有一个Upstart任务,启动一个服务的多个实例,基于自动启动多个upstart实例和重新启动实例进程 。 它正在工作,它启动所有的实例,但成功启动后,它只是挂起。 如果我Ctrl-C
出来,然后检查具有service status
的实例或查看ps
他们都成功开始,所以我不知道它挂在什么时候。
这是我的脚本:
description "all-my-workers" start on runlevel [2345] task console log env NUM_INSTANCES=1 env STARTING_PORT=42002 pre-start script for i in `seq 1 $NUM_INSTANCES`; do start my-worker N=$i PORT=$(($STARTING_PORT + $i)) done end script
当我做service start all-my-workers
我得到这个:
vagrant@vagrant-service:/etc/init$ sudo service all-my-workers start
然后它挂在那里,不再提示我。 正如我所说,我可以Ctrl-C
出去看看正在运行的工作人员:
vagrant@vagrant-service:/etc/init$ sudo service all-my-workers status all-my-workers start/running vagrant@vagrant-service:/etc/init$ sudo service my-worker status N=1 my-worker (1) start/running, process 21938
在ps
:
worker 21938 0.0 0.1 4392 612 ? Ss 21:46 0:00 /bin/sh -e /proc/self/fd/9 worker 21941 0.2 7.3 174076 27616 ? Sl 21:46 0:00 python /var/lib/my-system/script/start_worker.py
我不认为这个问题是在my-worker.conf
但以防万一:
description "my-worker" stop on stopping all-my-workers setuid worker setgid worker respawn instance $N console log env SCRIPT_PATH="/var/lib/my-system/script/" script export PROVIDER=vagrant export REGION=all export ENVIRONMENT=cert . /var/lib/my-system/.virtualenvs/my-system/bin/activate python $SCRIPT_PATH/start_worker.py END end script
谢谢一堆!
我假定my-worker
是一个长期的过程,并且你想有一个简单的方法来启动和拆卸多个并行的my-worker
实例。
如果是这样的话,你可能不希望all-my-workers
成为一项task
。 你会想要以下代替:
description "all-my-workers" start on runlevel [2345] console log env NUM_INSTANCES=1 env STARTING_PORT=42002 pre-start script for i in `seq 1 $NUM_INSTANCES`; do start my-worker N=$i PORT=$(($STARTING_PORT + $i)) done end script pre-stop script for i in `seq 1 $NUM_INSTANCES`; do stop my-worker N=$i PORT=$(($STARTING_PORT + $i)) || true done end script
然后你可以运行start all-my-workers
来启动所有my-worker
实例,然后运行stop all-my-workers
来阻止他们。 实际上, all-my-workers
成为家长的职责,负责管理孩子的工作。
你引用了两个SO答案,显示了这个管理孩子工作的父母工作的想法。 他们展示:
script
节的任务 pre-start
节的工作 你的父母的工作是一个pre-start
节的任务 ,这就是为什么你遇到这种奇怪的行为。
从这个Ask Ubuntu的答案引用这个弃用的文档 ,有两个非常重要的陈述(重点添加):
所有的作业文件都必须有一个exec或script节。 这指定了将要运行的工作。
额外的shell代码可以在exec或script指定的二进制文件或脚本之前或之后运行。 这些预计不会开始的过程,事实上,他们不能。 它们是为了准备环境和事后清理。
总之,由Upstart忽略(即不监控)由pre-start
节创建的任何后台进程。 相反,您必须使用exec
或script
来产生一个Upstart将监视的进程。
如果你省略了exec
/ script
节,会发生什么? 新贵会坐下来等待一个进程的产生。 因此,你可能写了一个while-true循环:
script while true; do true done end script
唯一的区别是while-true循环是一个活锁,而一个空节导致死锁。
了解了上述内容, Upstart任务文档最终引导我们进行下去:
如果没有“任务”关键字, 只要作业开始,导致作业启动的事件将被解除阻止 。 这意味着,这项工作已经发出了一个开始(7)的事件,开始启动前,开始其脚本/执行,后启动,并发出其开始(7)事件。
通过任务, 导致此作业开始的事件将被阻止,直到作业完全转换回停止状态 。 这意味着这个工作已经到达了前面提到的已经开始(7)的事件,并且也完成了它的停止后,排出了已经停止的(7)事件。
(如果你阅读关于启动和停止作业的文档,关于事件和状态的一些细节将更有意义)。
简单地说:
exec
/ script
节会被无限期阻止,因为它启动了一个长期的过程。 因此,Upstart在完成pre-start
节之后会停止阻止。 task
, exec
/ script
节预计会阻塞一个“有限”的时期,因为它正在启动一个短暂的过程。 因此,Ubstart阻塞,直到exec
/ script
节完成。 但是如果没有exec
/ script
节,会发生什么? 新贵坐在那里无限期地等待着要发起的事情,但这是不会发生的 。
stop
调用显然足以使其停止等待。 task
的情况下,Upstart会永远坐下来,直到你中断为止。 然而,由于还没有找到一个催生的过程,它仍然在技术上运行。 这就是为什么你可以查询中断后的状态,并看到all-my-workers start/running
。 如果出于某种原因,你真的想把你的父母工作变成一项任务,你实际上需要两个任务:一个是启动my-worker
实例,另一个是阻止他们。 您还需要删除stop on stopping all-my-workers
从my-worker
stop on stopping all-my-workers
节stop on stopping all-my-workers
。
开始-所有-我的同事:
description "starts all-my-workers" start on runlevel [2345] task console log env NUM_INSTANCES=1 env STARTING_PORT=42002 script for i in `seq 1 $NUM_INSTANCES`; do start my-worker N=$i PORT=$(($STARTING_PORT + $i)) done end script
停所有我的同事:
description "stops all-my-workers" start on runlevel [!2345] task console log env NUM_INSTANCES=1 env STARTING_PORT=42002 script for i in `seq 1 $NUM_INSTANCES`; do stop my-worker N=$i PORT=$(($STARTING_PORT + $i)) || true done end script