Задача Upstart зависает после успешного завершения

у меня есть задача выскочки, которая запускает несколько экземпляров службы на основе запуск нескольких выскочек экземпляров автоматически и перезапуск процессов экземпляра Upstart. Он работает и запускает все экземпляры, но после их успешного запуска он просто зависает. Если Я ... --5--> out, а затем проверьте экземпляры с помощью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

и потом он просто висит там и не спрашивать. Как я уже сказал, я могу!--5--> out и увидеть работающих рабочих:

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


Как Это Исправить?

я собираюсь предположить, что 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. A задание С script раздела
  2. A задание С pre-start раздела

ваша родительская работа-это задание С pre-start строфа, и вот почему вы сталкиваетесь с этим странное поведение.

скрипт против предварительного запуска

С это спросить Ubuntu ответ ссылкой эта устаревшая документация, есть два очень важных утверждения (с выделением добавлено):

все файлы заданий должны иметь строфу exec или script. указывает, что будет выполняться задание.

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

в общем, любые фоновые процессы, порожденные pre-start строфы игнорируются (т. е. не контролируются) выскочкой. Вместо этого ты!--42-->должны использовать exec или script чтобы породить процесс, который выскочка будет монитор.

что произойдет, если вы опустите exec/script строфа? Выскочка будет сидеть и ждать, пока процесс будет порожден. Таким образом, вы могли бы также написать while-true loop:

script
    while true; do
        true
    done
end script

единственная разница в том, что цикл while-true является живым замком, тогда как пустая строфа приводит к мертвой блокировке.

задания и задачи

зная, выше, выскочка документация для задач в конечном итоге приводит нас к тому, что происходит on:

без задачи сайта, события, которые вызывают запуск задания, будут разблокированы сразу после запуска задания. Это означает, что задание выпустило событие starting(7), запустило его перед запуском, запустило его скрипт/exec и после запуска и выпустило событие started(7).

С задач, события, которые приводят к запуску этого задания, будут заблокированы до тех пор, пока задание полностью не перейдет обратно в stopped. Это означает, что задание выполнялось до ранее упомянутого события started(7), а также завершило свою post-stop и выпустило событие stopped (7).

(некоторые особенности о событиях и состояниях будут иметь больше смысла, если вы прочитаете документацию о запуск и остановка рабочих мест).

С точки зрения simpiler:

  • С нормальной выскочкой,exec/script ожидается, что stanza будет блокировать бесконечно, потому что это запуск долгоживущего процесса. Таким образом, Upstart прекращает блокировку после завершения pre-start строфа.
  • С task на exec/script ожидается, что строфа будет блокироваться в течение "конечного" периода, потому что она запускает недолговечный процесс. Таким образом, Ubstart блокирует до после the exec/script строфа завершится.

но что произойдет, если нет exec/script строфа? Выскочка сидит и ждет бесконечно долго, чтобы что-то быть запущен, но это никогда.

  • в случае job, это нормально, потому что выскочка не блокирует во время ожидания процесса для нереста и вызова stop по-видимому, достаточно, чтобы он перестал ждать.
  • в случае task, однако, выскочка будет просто сидеть и висеть вечно - или пока вы не прервете его. Однако, поскольку он все еще не нашел порожденный процесс, он все еще технически работает. Вот почему вы можете запросить статус после прерывания и увидеть all-my-workers start/running.

ради интереса

если по какой-то причине вы действительно хотите сделать свою родительскую работу задачей, вам действительно понадобится два задачи: один, чтобы начать my-worker экземпляров и один, чтобы остановить их. Вам также необходимо удалить stop on stopping all-my-workers строфа из my-worker.

start-all-my-workers:

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