Супервизор: Как выполнить пользовательскую команду php, если какой-либо из рабочих, например, идентификатор процесса 123, останавливается - PullRequest
2 голосов
/ 05 августа 2020
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php artisan queue:work --tries=3 --queue=checkin_checkout
directory=/var/www/byjus-ams
autostart=true
autorestart=true
numprocs=5
redirect_stderr=true
stdout_logfile=/var/log/supervisor/supervisord.log
#stopwaitsecs=3600

На данный момент моя конфигурация для супервизора аналогична описанной выше, в которой параллельно запускаются 5 рабочих. Теперь я хочу: когда кто-то из рабочих погибает, я хочу запустить пользовательскую команду php (например: php artisan broadcast-process-kill ). Кто-нибудь знает, как обрабатывать такие события и запускать пользовательскую команду php после получения любого рабочего процесса и как ее настроить?

Даже упрощая ниже

supervisor> status
laravel-worker:laravel-worker_00   RUNNING   pid 9460, uptime 4:32:43
laravel-worker:laravel-worker_01   RUNNING   pid 15907, uptime 7:01:51
laravel-worker:laravel-worker_02   RUNNING   pid 22621, uptime 6:30:17
laravel-worker:laravel-worker_03   RUNNING   pid 15909, uptime 7:01:51
laravel-worker:laravel-worker_04   RUNNING   pid 24049, uptime 6:23:00
supervisor> 

Если я использую kill - 9 9460, я хочу запустить пользовательскую команду на. Кто-нибудь использовал пользовательские события?

1 Ответ

2 голосов
/ 06 августа 2020

Я нашел решение, в котором вы можете запустить команду перед фактической командой:

command=/bin/sh -c "php artisan broadcast-process-started; exec php artisan queue:work --tries=3 --queue=checkin_checkout"

Это будет выполняться broadcast-process-started всегда после того, как ваш рабочий перестанет работать И перезапустится.

By используя /bin/sh -c, вы составляете одну команду из этих двух. Добавив execute ко второй «фактической» команде, supervisord сможет обрабатывать свой pid.

Если вы опустите exe c, вы получите pid, разветвленный /bin/sh и все ваши команды внутри будут порождаться как подпроцессы, которые супервизор не может обработать. Поэтому при перезагрузке дочерние процессы сохраняются! Так что оставьте exe c!

Если вы перевернете команды, трансляция не будет выполняться.

Решение для прослушивания событий

supervisord config

[eventlistener:test-listener]
command=php /some/dir/event-listener.php <name>
events=PROCESS_STATE
stderr_logfile=/some/dir/event_err.log

Где <name> относится к [program:<name>] вашей конфигурации - программе, за которой вы хотите наблюдать.

прослушиватель событий. php

Записывается как php -script - вы также можете закодировать это как команду artisan.

<?php

declare(strict_types=1);

$programToListen = $argv[1] ?? false;
$eventsToListen = [
    'PROCESS_STATE_EXITED',
    'PROCESS_STATE_FATAL',
    'PROCESS_STATE_STOPPED',
];

if ($programToListen === false) {
    exit(1);
}

while (true) {
    // tell supervisord we are ready to receive event-headers
    echo 'READY' . PHP_EOL;
    
    $eventHeader = parseEventHeader(fgets(STDIN));
    
    if (
        ($eventHeader['groupname'] ?? '') === $programToListen &&
        in_array(($eventHeader['eventname'] ?? ''), $eventsToListen)
    ) {
        debug(sprintf(
            'Handling %s of %s',
            $eventHeader['eventname'],
            $eventHeader['groupname']
        ));
       
        // add your code here
        // exec('php artisan ...') for example
    }

    // Tell supervisord we are done handling the event-header
    echo 'RESULT 2' . PHP_EOL . 'OK';
}

function debug(string $message): void {
    fwrite(STDERR, $message . PHP_EOL);
    return;
}

function parseEventHeader(string $eventHeaderString): array {
    $keyValuePairs = explode(' ', $eventHeaderString);

    $eventArray = [];
    foreach ($keyValuePairs as $keyValuePair) {
        $keyValue = explode(':', $keyValuePair);

        $eventArray[$keyValue[0]] = $keyValue[1];
    }

    return $eventArray;
}

exit(0)
?>

мелочи

  • Вместо использования echo вы можете также fwrite(STDOUT,..), но это было слишком необычно для меня.
  • Я оставил свой механизм отладки в на случай, если вы захотите поиграть с ним (вы: D).

дополнительная информация

  • Здесь доступны Типы процессов для обработки.
  • Здесь Состояния подпроцесса (которые приводят к событиям).
  • Уведомление слушателя событий протокол (наши echo сообщения и синтаксический анализ заголовка события).
  • PROCESS_STATE_EXITED будет запущен на > kill или конец выполнения
  • PROCESS_STATE_STOPPED будет запущен супервизором (restart et c.)
  • Мне не удалось запустить PROCESS_STATE_FATAL - но я буду его слушать, просто в случае:)
...