Я запускаю несколько экземпляров рабочего, как описано в этом ответе: https://stackoverflow.com/questions/8681974/starting-multiple-upstart-instances-automatically.
** Вопрос: Могу ли я перезапустить все экземпляры одновременно?
Для запуска рабочих я могу сделать следующее:
initctl start my-workers
Что затем позволит мне сделать:
initctl status worker N=1 worker (1) start/running, process 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
В файле 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
. Затем, конечно, когда он снова запустится, он снова запустит рабочих.
(К вашему сведению, stop on shutdown
ничего не делает, поскольку shutdown
не является системным событием. man upstart-events
для всех определенных событий), поэтому вы также должны изменить my-workers на stop on runlevel [06]
.
Я попробовал это с примером, приведенным выше, и получил ответ 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
В конец
цикла for-loop в 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
и это сработало!
Рассмотрите возможность добавления в файл worker.conf еще одного события:
stop on shutdown or workers-stop
Тогда вы сможете вызывать из командной строки
sudo initctl emit workers-stop
Вы можете добавить аналогичное событие для запуска рабочих. Чтобы добиться перезапуска всех рабочих, создайте задачу, которая будет испускать события workers-stop, а затем workers-start.
По сути, вы должны иметь процесс, который выполняет множество стоп
и команды старт
для всех П=1
, комбинация N=2
.
Простой способ сделать это-пара Баш для
петли внутри себя старпома сценарийстрофы. Однако, если процессы, потребуется некоторое время, чтобы остановить (например, потому, что они работают над чем-то и они принимают
прекращается после обработав их текущей работы) это неэффективно, так как приходится ждать один, чтобы остановить, прежде чем отправить сигнал к следующему.
Поэтому я создал скрипт выскочка, которая останавливает их параллельно https://github.com/elifesciences/builder-base-formula/blob/master/elife/config/etc-init-multiple-processes-parallel.conf
Сценарий составлен соли, используя в качестве входных карту названия процесса, сколько их там. Вот результат выборки:
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