Подтвердить что ты не робот

Перезапуск процессов экземпляра Upstart

Я запускаю несколько экземпляров рабочего, как описано в этом ответе: Автоматически запускать несколько экземпляров upstart

Вопрос: Можно ли перезапустить все экземпляры одновременно?

Чтобы начать работу с моими работниками, я могу:

initctl start my-workers

Что тогда позволяет мне делать:

initctl status worker N = 1 рабочий (1) запуск/запуск, процесс 551

initctl status worker N = 2 worker (2) start/running, process 552

Есть ли способ сделать что-то вроде этого:

initctl restart my-workers

Я хотел бы иметь возможность перезапускать все экземпляры, не зная, сколько из них работает.

Вот мой 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
4b9b3361

Ответ 1

В worker.conf вам просто нужно изменить эту строку:

stop on shutdown

To:

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. Затем, конечно, когда он снова запустится, он снова запустит рабочих.

(FYI, stop on shutdown ничего не делает, поскольку shutdown не является системным событием. man upstart-events для всех определенных событий), поэтому вы должны также изменить моих работников на stop on runlevel [06]

Ответ 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

end для цикла for в my-workers.conf представляется неправильным синтаксисом. Я заменил

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

Рассмотрим добавление к work.conf еще одного события:

stop on shutdown or workers-stop

Затем вы можете вызывать из командной строки

sudo initctl emit workers-stop

Вы можете добавить подобное событие, чтобы начать работу. Чтобы добиться перезапуска, все работники создают задачу, которая будет запускать события "рабочие-стоп", а затем "рабочие".

Ответ 4

По существу, вам нужен процесс, который выполняет команды stop и start для всех ваших комбинаций N=1, N=2.

Простым способом сделать это является пара циклов bash for внутри строфы exec script. Однако, если для выполнения процессов требуется некоторое время (например, потому что они работают над чем-то, и они принимают SIGTERM после обработки своего текущего задания), это неэффективно, так как вам нужно дождаться остановки до отправки сигнала на следующий.

Поэтому я построил Upstart script, который останавливает их параллельно в https://github.com/elifesciences/builder-base-formula/blob/master/elife/config/etc-init-multiple-processes-parallel.conf

script скомпилирован Солт, используя для ввода карту имен процессов, сколько их есть. Вот пример результата:

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