【问题标题】:Restarting Upstart instance processes重启 Upstart 实例进程
【发布时间】:2012-08-18 12:28:55
【问题描述】:

我正在运行一个工人的多个实例,如以下答案所述:Starting multiple upstart instances automatically

问题:我可以一次重启所有实例吗?

要开始我的工人,我可以这样做:

initctl 启动我的工人

然后我可以这样做:

initctl status worker N=1 worker (1) 启动/运行,进程 551

initctl status worker N=2 worker (2) 启动/运行,进程 552

有没有办法做这样的事情:

initctl 重启我的工人

我希望能够重新启动所有实例,而不必知道有多少正在运行。

这是我的 my-workers.conf

start on stopped cloud-init
stop on shutdown

env NUM_WORKERS=4

script
  for i in `seq 1 $NUM_WORKERS`
    do
      start worker N=$i
    done
end script

还有worker.conf

stop on shutdown

chdir /path/to/current

respawn

instance $N

script
  exec su -c "/home/worker/.rvm/bin/rvm-shell -c 'bundle exec rake work 2>&1 >> /var/log/worker-$N.log'" worker
end script

【问题讨论】:

    标签: ubuntu upstart


    【解决方案1】:

    worker.conf你只需要改变这一行:

    stop on shutdown
    

    收件人:

    stop on stopping my-workers
    

    并将my-workers.conf 更改为使用pre-start 而不是script

    pre-start script
      for i in `seq 1 $NUM_WORKERS`
      do
        start worker N=$i
      done
    end script
    

    现在my-workers 将保持状态:由于工作发生在pre-start 中,my-workers 主进程将不存在,因此不会退出。 stop on stopping my-workers 使工作人员在 my-workers 停止时停止。当然,当它再次启动时,它会再次启动工人。

    (仅供参考,stop on shutdown 什么都不做,因为shutdown 不是系统事件。man upstart-events 用于所有已定义的事件)所以您还应该将 my-workers 更改为 stop on runlevel [06]

    【讨论】:

    • 我花了一段时间才明白你的意思,但一旦我明白了...... 大吃一惊
    • @Evgeny 也一样,哈哈。如果像我一样,也可能是 Evgeny,你只花了 5 分钟试图了解这里发生了什么:基本上 my-workers.conf 生成多个新贵脚本并退出,但每个 worker.conf 现在都有 stop on stopping my-workers 行,所以当你试图停止已经停止的 my-workers 进程,工人仍然会听它并死去。因此,“重新启动” my-workers,即使它之前并没有真正运行,也会产生杀死工人(停止)并再次运行预启动脚本(启动),再次产生它们的效果。
    • 它可以工作,但它很hackish。 service my-workers start 实际上会挂起。 Upstart 文档指出 All job files must have either an exec or script stanza. pre-start script and post-stop script - These are not expected to start the process, in fact, they can't.。也许最好只创建另一个作业来停止或重新启动工人。
    • 这是(现在?)定义为抽象工作:upstart.ubuntu.com/cookbook/#abstract-job - 所以看起来没问题。
    【解决方案2】:

    我用上面的例子和 SpamapS 的答案试了一下,我收到了:

    init: my-workers pre-start process (22955) terminated with status 127
    

    /var/log/upstart/my-workers.log我发现了问题:

    /proc/self/fd/9: 6: /proc/self/fd/9: end: not found
    

    my-workers.conf 中 for 循环的 end 似乎语法错误。 我换了

    script
      for i in `seq 1 $NUM_WORKERS`
        do
          start worker N=$i
        done
      end
    end script
    

    script
      for i in `seq 1 $NUM_WORKERS`
      do
        start worker N=$i
      done
    end script
    

    它成功了!

    【讨论】:

      【解决方案3】:

      考虑在 worker.conf 中再添加一个事件:

      stop on shutdown or workers-stop
      

      然后就可以从命令行调用了

      sudo initctl emit workers-stop
      

      您可以添加类似的事件来启动工作人员。要实现重新启动所有工作人员,请创建一个任务,该任务将发出工作人员停止和工作人员启动事件。

      【讨论】:

        【解决方案4】:

        基本上,您需要有一个进程来为您的所有N=1N=2 组合执行许多stopstart 命令。

        执行此操作的简单方法是在 exec script 节中使用几个 bash for 循环。但是,如果进程需要一些时间才能停止(例如,因为他们正在处理某事并且在处理完当前工作后他们正在接受SIGTERM),那么这是低效的,因为您必须等待一个停止才能将信号发送到下一个。

        因此,我构建了一个 Upstart 脚本,在 https://github.com/elifesciences/builder-base-formula/blob/master/elife/config/etc-init-multiple-processes-parallel.conf 处并行停止它们

        该脚本由 Salt 编译,使用进程名称与进程数量的映射作为输入。这是一个示例结果:

        description "(Re)starts all instances, in parallel"
        # http://upstart.ubuntu.com/cookbook/#start-on
        start on (local-filesystems and net-device-up IFACE!=lo)
        task
        script
            timeout=300
            echo "--------"
        
            echo "Current status of 5 elife-bot-worker processes"
            echo "Now is" $(date -Iseconds)
            for i in `seq 1 5`
            do
                status elife-bot-worker ID=$i || true
            done
            echo "Stopping asynchronously 5 elife-bot-worker processes"
            echo "Now is" $(date -Iseconds)
            for i in `seq 1 5`
            do
                (stop elife-bot-worker ID=$i &) || true
            done
        
            for i in `seq 1 5`
            do
                echo "Waiting for elife-bot-worker $i to stop"
                echo "Now is" $(date -Iseconds)
                counter=0
                while true
                do
                    if [ "$counter" -gt "$timeout" ]
                    then
                        echo "It shouldn't take more than $timeout seconds to kill all the elife-bot-worker processes"
                        exit 1
                    fi
                    status elife-bot-worker ID=$i 2>&1 | grep "Unknown instance" && break
                    sleep 1
                    counter=$((counter + 1))
                done
            done
            echo "Stopped all elife-bot-worker processes"
        
            echo "Starting 5 elife-bot-worker processes"
            for i in `seq 1 5`
            do
                start elife-bot-worker ID=$i
            done
            echo "Started 5 elife-bot-worker processes"
        
        end script
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-18
          • 1970-01-01
          • 1970-01-01
          • 2013-07-26
          • 1970-01-01
          • 2011-11-07
          相关资源
          最近更新 更多