Как остановить процесс Supervisord, не убивая программу, которую он контролирует?

Я использую Supervisord для постоянного запуска некоторых программ индексирования. Каждый раз, когда запускается индексатор, он захватывает определенный набор документов, индексирует их, а затем завершает работу. Затем этот процесс Supervisord порождает другую такую ​​же программу индексатора, и этот индексатор захватывает новый набор документов для индексации.

Иногда мне нужно остановить процесс Supervisord, который запускает эти программы индексатора. Однако когда я это делаю, это всегда убивает программу индексатора посреди работы.

Что я хотел бы сделать, так это остановить процесс Supervisord, чтобы программа индексатора, которая в данный момент выполняется, выполнялась до завершения, но процесс Supervisord не порождал другой индексатор.

Вот мои настройки supervisord.conf для этого процесса:

; TRIGGERING INDEXERS
;
[program:indexer]
command=php /data/app/index_company.php
process_name=%(program_name)s_%(process_num)d
redirect_stderr=true
stdout_capture_maxbytes=10MB
stdout_logfile_backups=0
numprocs=5
startsecs=0
autostart=false
autorestart=true
[group:indexers]
programs=indexer

person T. Brian Jones    schedule 24.08.2013    source источник


Ответы (1)


supervisord подаст сигнал SIGTERM, когда будет запрошен стоп. Ваш ребенок, скорее всего, сможет поймать и обработать этот сигнал (конфигурация stopsignal может изменить отправленный сигнал).

Поскольку вы используете PHP, pcntl_signal кажется правильным решением. Я не могу догадаться, как на самом деле работает ваш мастер, я предполагаю, что это просто бесконечный цикл, однопоточный. Вот очень примитивный пример:

<?php
    $stop_requested = false;

    pcntl_signal( SIGTERM, function() {
        global $stop_requested;
        $stop_requested = true;
    } );

    while ( true ) {
        do_work();
        if ( $stop_requested ) break;
    }
?>

Теперь, когда вы попытаетесь остановить процесс, он не будет остановлен. Однако он все равно остановится через 10 секунд. Почему?

Потому что stopwaitsecs по умолчанию установлен на 10 секунд. Это время supervisord будет ждать отправки SIGKILL, который убьет ваш процесс. Установка того, что, как вы знаете, будет работать хорошо, например, 600 секунд позволит вашему индексатору завершить работу до завершения работы.

[program:indexer]
command=php index.php
stopwaitsecs=600

Вышеупомянутого должно быть достаточно, чтобы ваш индексатор мог корректно остановиться. Однако есть по крайней мере одна проблема с длительным временем ожидания: supervisorctl будет продолжать ждать и не обрабатывать дальнейшие команды, пока процесс не остановится. Вы можете запустить другой экземпляр. Не уверен, что происходит с веб-клиентом (может продолжать загружаться и ожидать ответа).

Хотя описанный выше подход, вероятно, подойдет вам, вам, вероятно, следует пересмотреть свои настройки и не ждать supervisord так долго ожидания завершения работы. Вашим индексаторам, вероятно, следует остановиться как можно скорее, не выполняя больше работы, сбрасывая результаты или что-то еще, что они делают. Небольшие фрагменты полезной работы гарантируют, что они завершатся в разумные сроки.

Надеюсь это поможет. Дай мне знать, как дела.

person soulseekah    schedule 30.11.2013
comment
Очень полезный!. Я заметил, что SIGTERM по умолчанию убивает скрипт php, если не используется pcntl_signal и не указан обратный вызов. Например, если я запускаю сценарий, подобный приведенному выше, он немедленно завершается, если я не определил функцию обратного вызова SIGTERM. Как только обратный вызов SIGTERM определен, сценарий продолжает выполняться, пока он не будет уничтожен или не обработан. Следует также отметить, что все эти сигналы немедленно завершают работу php-скрипта, находящегося в настоящее время внутри функции sleep(). См. Здесь: ссылка - person Benjamin Oman; 26.05.2016