Upstart任务在成功完成后挂起

时间:2015-01-23 21:53:31

标签: linux ubuntu upstart

我有一个Upstart任务,可以根据Starting multiple upstart instances automaticallyRestarting Upstart instance processes启动多个服务实例。它正在工作,它启动所有实例,但在它成功启动后,它只是挂起。如果我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

非常感谢!

1 个答案:

答案 0 :(得分: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

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

为什么?

你引用了两个SO答案,显示了管理儿童工作的父母工作的想法。他们表示:

  1. 带有script节的任务
  2. 带有pre-start节的作业
  3. 您的父作业是一个带有pre-start节的任务,这就是您遇到这种奇怪行为的原因。

    script vs pre-start

    引用this Ask Ubuntu answerthis deprecated documentation,有两个非常重要的陈述(重点已添加):

      

    所有作业文件必须具有exec或script节。 指定将为该作业运行的内容。

         

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

    总之,Upstart会忽略pre-start节产生的任何后台进程(即不受监视)。相反,您必须使用execscript来生成Upstart将监控的流程。

    如果省略exec / script节会怎样? Upstart将坐下来等待一个进程产生。因此,您可能已经编写了一个while-true循环:

    script
        while true; do
            true
        done
    end script
    

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

    工作与任务

    了解上述内容后,the Upstart documentation for tasks最终将我们带入了正在发生的事情:

      

    没有'任务'关键字一旦作业启动,将立即取消阻止导致作业启动的事件。这意味着作业已发出一个start(7)事件,运行其pre-start,开始其script / exec和post-start,并发出其started(7)事件。

         

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

    (如果您阅读有关starting and stopping jobs的文档,有关事件和状态的一些细节会更有意义。

    以simpiler术语:

    • 对于正常的Upstart作业,exec / script节预计将无限期阻止,因为它启动了一个长期存在的过程。因此,Upstart在完成pre-start节后停止阻止。
    • 使用taskexec / script节预计将阻止"有限"期间,因为它启动了一个短暂的过程。因此,Ubstart会阻塞之后 exec / script节完成。

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

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

    感兴趣的清酒

    如果由于某种原因,你真的想让你的父作业成为一项任务,你实际上需要两个任务:一个用于启动my-worker个实例,另一个用于阻止它们。您还需要从stop on stopping all-my-workers删除my-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
    

    停止,所有我的工人:

    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