PHPで実装されたDaemonクラス。サーバー上の crontab からキューやスケジュールされたタスクを実装できます。
使用する場合は、このクラスを継承し、_doTaskメソッドをオーバーライドし、main経由で初期化して実行します。
- クラスデーモン{
- const DLOG_TO_CONSOLE = 1;
- const DLOG_NOTICE = 2;
- const DLOG_WARNING = 4;
- const DLOG_ERROR = 8;
- const DLOG_CRITICAL = 16;
- const DAPC_PATH = ' /tmp/daemon_apc_keys';
- /**
- * ユーザーID
- *
- * @var int
- */
- public $userID = 65534; // 誰も
- /**
- * グループID
- *
- * @var integer
- */
- public $groupID = 65533; // 誰も
- /**
- * ID 設定失敗時にデーモンを終了します ?
- *
- * @var bool
- * @since 1.0.3
- */
- public $requireSetIdentity = false;
- /**
- * PID ファイルへのパス
- *
- * @var string
- * @since 1.0.1
- */
- public $pidFileLocation = '/tmp/daemon.pid';
- /**
- * processLocation
- * プロセス情報記録ディレクトリ
- *
- * @var string
- */
- public $processLocation = '';
- /**
- * processHeartLocation
- * プロセスハートビートパケットファイル
- *
- * @var string
- */
- public $processHeartLocation = '';
- /**
- * ホームパス
- *
- * @var string
- * @since 1.0
- */
- public $homePath = '/';
-
- /**
- * 現在のプロセス ID
- *
- * @var int
- * @since 1.0
- */
- protected $_pid = 0;
- /**
- * このプロセスは子供ですか
- *
- * @var boolean
- * @since 1.0
- */
- protected $_isChildren = false;
- /**
- * デーモンは実行されていますか
- *
- * @var boolean
- * @since 1.0
- */
- protected $_isRunning = false;
- /**
- * コンストラクター
- *
- * @return void
- */
- public function __construct() {
- error_reporting(0);
- set_time_limit(0);
- ob_implicit_flush();
- register_shutdown_function(array(&$this, 'releaseDaemon')) ;
- }
- /**
- * プロセス開始
- *
- * @return bool
- */
- public function main() {
- $this->_logMessage('デーモンの起動');
-
- if (!$this->_daemonize()) {
- $this->_logMessage('デーモンを起動できませんでした', self::DLOG_ERROR);
-
- return false;
- }
-
- $this->_logMessage('実行中...');
-
- $this- >_isRunning = true;
-
- while ($this->_isRunning) {
- $this->_doTask();
- }
-
- return true;
- }
-
- /**
- * プロセスを停止します
- *
- * @return void
- */
- public function stop() {
-
- $this->_logMessage('デーモンの停止');
-
- $this->_isRunning = false;
- }
-
- /**
- * タスクを実行します
- *
- * @return void
- */
- 保護された関数 _doTask() {
- // このメソッドをオーバーライドします
- }
-
- /**
- * _logMessage
- * ログを記録します
- *
- * @param 文字列メッセージ
- * @param 整数レベル
- * @return void
- */
- protected function _logMessage($msg, $level = self::DLOG_NOTICE) {
- // このメソッドをオーバーライドします
- }
-
- /**
- * デーモン化
- *
- * ほとんどのデーモンが持ついくつかのルールまたは特性:
- * 1) デーモンが既に実行されているかどうかを確認する
- * 2) 子プロセスをフォークする
- * 3) ID を設定する
- * 4) 現在のプロセスをセッション レイヤーにする
- * 5) プロセスIDをファイルに書き込む
- * 6) ホームパスを変更する
- * 7) umask(0)
- *
- * @access private
- * @since 1.0
- * @return void
- */
- プライベート関数 _daemonize() {
-
- ob_end_flush();
-
- if ($this->_isDaemonRunning()) {
- // デーモンはすでに実行されています。終了します
- return false;
- }
-
- if (!$this->_fork()) {
- // フォークできませんでした。 Exiting.
- return false;
- }
-
- if (!$this->setIdentity() && $this->gt;requireSetIdentity) {
- // 必要な ID セットが失敗しました。終了中
- return false;
- }
-
- if (!posix_setsid()) {
- $this->_logMessage('現在のプロセスをセッション リーダーにできませんでした', self::DLOG_ERROR);
-
- return false;
- }
-
- if (!$fp = fopen($this->pidFileLocation, 'w')) {
- $this->_logMessage('PID ファイルに書き込めませんでした', self::DLOG_ERROR);
- return false;
- } else {
- fputs($fp, $this->_pid);
- fclose($fp);
- }
-
- // 書入监控日志
- $this->writeProcess();
-
- chdir($this->homePath);
- umask(0);
-
- declare(ticks = 1);
-
- pcntl_signal(SIGCHLD 、array(&$this, 'sigHandler'));
- pcntl_signal(SIGTERM, array(&$this, 'sigHandler'));
- pcntl_signal(SIGUSR1, array(&$this, 'sigHandler'));
- pcntl_signal( SIGUSR2, array(&$this, 'sigHandler'));
-
- return true;
- }
-
- /**
- * Cheks はデーモンがすでに実行されています
- *
- * @return bool
- */
- プライベート関数 _isDaemonRunning() {
-
- $oldPid = file_get_contents($this-> pidFileLocation);
-
- if ($oldPid !== false && posix_kill(trim($oldPid),0))
- {
- $this->_logMessage('デーモンはすでに PID で実行中です: '.$oldPid, (self: :DLOG_TO_CONSOLE self::DLOG_ERROR));
-
- return true;
- }
- else
- {
- return false;
- }
- }
-
- /**
- * フォークプロセス
- *
- * @return bool
- */
- プライベート関数 _fork() {
-
- $this ->_logMessage('フォーク中...');
-
- $pid = pcntl_fork();
-
- if ($pid == -1) {
- // 出错
- $this->_logMessage('フォークできませんでした', self::DLOG_ERROR);
-
- return false;
- } elseif ($pid) {
- // 父进程
- $this->_logMessage('親殺し');
-
- exit();
- } else {
- // フォーク的な子手続き
- $this->_isChildren = true;
- $this->_pid = posix_getpid();
-
- return true;
- }
- }
-
- /**
- * デーモンの ID を設定し、結果を返します
- *
- * @return bool
- */
- private function _setIdentity() {
-
- if (!posix_setgid($this->groupID) || !posix_setuid($this->userID))
- {
- $this->_logMessage('ID を設定できませんでした', self::DLOG_WARNING);
-
- return false;
- }
- else
- {
- return true;
- }
- }
-
- /**
- * シグナルハンドラー
- *
- * @access public
- * @since 1.0
- * @return void
- */
- public function sigHandler($sigNo) {
-
- switch ($sigNo)
- {
- case SIGTERM: // Shutdown
- $this->_logMessage('Shutdown signal' );
- exit();
- Break;
-
- case SIGCHLD: // Halt
- $this->_logMessage('Halt signal');
- while (pcntl_waitpid(-1, $status, WNOHANG) > 0);
- Break;
- case SIGUSR1: // ユーザー定義
- $this->_logMessage('ユーザー定義シグナル 1');
- $this->_sigHandlerUser1();
- Break;
- case SIGUSR2: // ユーザー-定義済み
- $this->_logMessage('ユーザー定義シグナル 2');
- $this->_sigHandlerUser2();
- Break;
- }
- }
-
- /**
- * シグナルハンドラー: USR1
- * 主に、各プロセスでキャッシュされたドメイン名の DNS 解決レコードを定期的にクリーンアップするために使用されます
- *
- * @return void
- */
- protected function _sigHandlerUser1( ) {
- apc_clear_cache('user');
- }
-
- /**
- * シグナルハンドラー: USR2
- * ハートビートパケットファイルの書き込みに使用されます
- *
- * @return void
- */
- protected function _sigHandlerUser2() {
-
- $this->_initProcessLocation();
-
- file_put_contents($this->processHeartLocation 、 time());
-
- return true;
- }
-
- /**
- * デーモンの PID ファイルを解放します
- * このメソッドは終了時に呼び出されます (デストラクターのような)
- *
- * @return void
- */
- public function releaseDaemon() {
-
- if ($this->_isChildren && is_file($this->pidFileLocation) ) {
- $this->_logMessage('デーモンの解放');
-
- unlink($this->pidFileLocation);
- }
- }
-
- /**
- * writeProcess
- * 現在のプロセス情報を監視ログに書き込みます。別のスクリプトが監視ログのデータをスキャンし、応答がない場合はプロセスを再起動します
- *
- * @return void
- */
- public function writeProcess() {
-
- // proc を初期化します
- $this->_initProcessLocation();
-
- $command = trim(implode(' ', $_SERVER['argv ']));
-
- // プロセスのディレクトリを指定します
- $processDir = $this->processLocation . $this->_pid;
- $processCmdFile = $processDir ;
- $processPwdFile = $processDir . '/pwd';
-
- // すべてのプロセスが配置されているディレクトリ
- if (!is_dir($this->processLocation)) {
- mkdir($this->processLocation, 0777);
- chmod($ processDir, 0777);
- }
-
- // 重複したプロセス レコードをクエリします
- $pDirObject = dir($this->processLocation);
- while ($pDirObject && (($pid = $pDirObject->read ()) !== false)) {
- if ($pid == '.' || $pid == '..' || intval($pid) != $pid) {
- continue;
- }
-
- $pDir = $this->processLocation . $pid;
- $pCmdFile = $pDir ;
- $pPwdFile = '/pwd';
- $pHeartFile . heart';
-
- // cmd check に基づいて同じパラメータでプロセスを開始します if (is_file($pCmdFile) &&rim(file_get_contents($pCmdFile)) == $command) {
- unlink($pCmdFile);
- unlink ($pPwdFile);
- unlink($pHeartFile);
-
- // 削除されたディレクトリにはキャッシュがあります
- usleep(1000);
-
- rmdir($pDir);
- }
- }
-
- // 新しいプロセスディレクトリ
- if (!is_dir ($processDir)) {
- mkdir($processDir, 0777);
- chmod($processDir, 0777);
- }
-
- // コマンドパラメータを書き込みます
- file_put_contents($processCmdFile, $command);
- file_put_contents($processPwdFile, $ _SERVER['PWD' ]);
-
- // 書き込みファイルはキャッシュされます
- usleep(1000);
-
- return true;
- }
-
- /**
- * _initProcessLocation
- * 初期化
- *
- * @return void
- */
- protected function _initProcessLocation() {
-
- $this ->processLocation = ROOT_PATH . '/app/data/proc';
- $this->processHeartLocation = $this->processLocation '/heart';
- }
- }
-
-
コードをコピー
|