Upstart任务在成功完成后挂起

JDi*_*rro 9 linux ubuntu upstart

我有一个Upstart任务,它基于自动启动多个upstart实例Restarting 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
Run Code Online (Sandbox Code Playgroud)

当我这样做时,service start all-my-workers我得到这个:

vagrant@vagrant-service:/etc/init$ sudo service all-my-workers start
Run Code Online (Sandbox Code Playgroud)

然后它只是挂在那里,并没有再提示我.正如我所说,我可以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
Run Code Online (Sandbox Code Playgroud)

并在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
Run Code Online (Sandbox Code Playgroud)

我不认为问题在于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
Run Code Online (Sandbox Code Playgroud)

谢谢你!

cyf*_*r01 9

我如何解决它?

我将假设这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
Run Code Online (Sandbox Code Playgroud)

然后,您可以运行start all-my-workers以启动所有my-worker实例,然后运行stop all-my-workers以停止它们.实际上,all-my-workers成为管理启动和停止子工作的父工作.

为什么?

你引用了两个SO答案,显示了一个管理子工作的父母工作的想法.他们展示:

  1. 一节有任务的任务script
  2. 一个岗位pre-start

你的父工作是一个带有节的任务pre-start,这就是你遇到这种奇怪行为的原因.

脚本与预启动

这个引用这个已弃用的文档的Ask Ubuntu回答中,有两个非常重要的陈述(重点是添加):

所有作业文件必须具有exec或脚本节.这指定了将为作业运行的内容.

可以在使用exec或script指定的二进制文件或脚本之前之后运行其他shell代码.预计这些都不会启动这个过程,事实上,他们不能.它们用于准备环境并在之后进行清理.

总之,pre-startUpstart忽略(即,不监视)由该节生成的任何后台进程.相反,您必须使用execscript生成Upstart将监视的进程.

如果省略exec/ scriptstanza 会发生什么?Upstart将坐下来等待一个进程产生.因此,您可能已经编写了一个while-true循环:

script
    while true; do
        true
    done
end script
Run Code Online (Sandbox Code Playgroud)

唯一的区别是while-true循环是一个活锁,而一个空节导致死锁.

工作与任务

知道了上述内容,Upstart的任务文档最终引导我们了解正在发生的事情:

如果没有'task'关键字,一旦作业启动,将立即取消阻止导致作业启动的事件.这意味着作业已发出一个start(7)事件,运行其pre-start,开始其脚本/ exec,并启动后,并发出其started(7)事件.

使用任务时,将阻止导致此作业启动的事件,直到作业完全转换回停止.这意味着作业已经运行到前面提到的started(7)事件,并且还完成了它的post-stop,并发出了stop(7)事件.

(如果您阅读有关启动和停止工作的文档,有关事件和状态的一些细节会更有意义).

在simpiler术语中:

  • 使用正常的Upstart作业,exec/ scriptstanza预计会无限期地阻塞,因为它启动了一个长期存在的进程.因此,一旦完成pre-start节,Upstart就会停止阻塞.
  • 有了a task,exec/ scriptstanza预计会阻止"有限"时期,因为它正在启动一个短暂的过程.因此,Ubstart块,直到之后exec/ script节已完成.

但如果没有exec/ script节,会发生什么?Upstart坐下来无限期地等待发布的东西,但这种情况永远不会发生.

  • 在a的情况下job,这很好,因为Upstart在等待进程生成时不会阻塞,并且调用stop显然足以让它停止等待.
  • task但是,在a的情况下,Upstart将永远坐下并挂起 - 或直到你打断它.但是,因为它仍然没有找到生成的进程,所以它仍然在技术上运行.这就是为什么你可以在中断后查询状态并查看all-my-workers start/running.

为了兴趣的缘故

如果由于某种原因,你真的想让你的父作业成为一个任务,你实际上需要两个任务:一个是启动my-worker实例而另一个是停止它们.您还需要从中删除该stop on stopping all-my-workersmy-worker.

开始 - 所有 - 我的同事:

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
Run Code Online (Sandbox Code Playgroud)

停所有我的同事:

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
Run Code Online (Sandbox Code Playgroud)