Edited at

supervisorでデーモン化したスクリプトをきちんと正常終了させるようにしようとしたけどできなかった件(訂正:できた)

More than 3 years have passed since last update.


やりたいこと

SQSとかRabbitMQとかのキューを監視して処理するworkerスクリプトを書いて、それをsupervisorでデーモン化して使ってるだけど、スクリプトのリロードの時とか、サーバー再起動の時に、きちんとSIGTERMとかのシグナルによってきちんと正常終了したいと思いやってみたけど、できんかった。

下記のように、Aして、Bして、Cして完了、みたいな処理があったとして、

task_a のあとで処理をブチ切りされたら、不整合が生じるのでなんとかしたい。

while (1) {

$message = get_queue_message();
task_a($message);
task_b($message);
task_c($message);
// SIGHUP されたらここで終了したい。
}

まとめるとこんな感じ


  • SQSとかRabbitMQとかのキューを監視して処理するworkerスクリプトを書いた

  • 無限ループでずっとキューを監視し、あったら処理

  • スクリプトをsupervisord でデーモン化

  • スクリプトはphpで記述

  • SIGTERMとかのシグナルもらったら、処理の途中ではなく、キリのよいところでお行儀よく終了したい。


書いてみたスクリプト


こんな感じのやつ。

<?php

declare(ticks = 1);

class Worker
{
static $shutdown = 0;

public function run()
{
$i = 0;
while (1) {
printf("[$i] task_a \n");
printf("[$i] task_b \n");
printf("[$i] task_c \n");

if (self::$shutdown == 1) {
echo "shutdown!!!\n";
exit;
}
}
}

/**
* シグナルを受け取った時の処理
*/

public static function sigHandler($signo)
{
self::$shutdown = 1;
}
}

// シグナルハンドラの設定
pcntl_signal(SIGTERM, "Worker::sigHandler");
pcntl_signal(SIGHUP, "Worker::sigHandler");

$worker = new Worker();
$worker->run();


何がだめだったか。

supervisorctl start all とか、supervisorctl stop all とかしても、コンソールが固まって返ってこない。

推測だけど、supervisor がなんかスクリプトのプロセスを後ろにおいやる処理とかしてるのと、worker の中でシグナルハンドラを再定義してるのが衝突してるのかも。supervisorの仕組みがよく分かってないのでよくわからん。

こういう処理実装するときってどうするのがいいんだろ。

教えてエロいひと。


追記(2015/02/18)

supervisor をバージョン 3にあげたら、問題なく動きました。