PHPでUNIXデーモンを実装するためのクラス

さて、データを処理するために何らかのサーバー部分を実装する必要があるという事実に対処する必要があるという事実から始めましょう。 当然、サーバー側はデーモンとして実装するのが最も便利です。 かつて、Pythonで書かれたデーモンを実装する同様のクラスに出会いました。 そして先週、私はPHPで同じ作成を書くことにしました。それは悪くないことがわかったので、評価する必要があります。



それで、すべてのソースがbitbucket.orgGitHubにあるという事実から始めましょう(お好みで)、ドキュメントもそこに書かれています。 実際、クラス自体のコードは次のとおりです。



<?php /* Author: Petr Bondarenko E-mail: public@shamanis.com Date: 31 May 2012 License: BSD Description: Class for create UNIX-daemon */ class DaemonException extends Exception {} abstract class DaemonPHP { protected $_baseDir; protected $_chrootDir = null; protected $_pid; protected $_log; protected $_err; /** *  .    pid- * @param string $path    PID- */ public function __construct($path=null) { $this->_baseDir = dirname(__FILE__); $this->_log = $this->_baseDir . '/daemon-php.log'; $this->_err = $this->_baseDir . '/daemon-php.err'; if ($path === null) { $this->_pid = $this->_baseDir . '/daemon-php.pid'; } else { $this->_pid = $path; } } /** *    log- * @param string $path    log- * @return DaemonPHP */ final public function setLog($path) { $this->_log = $path; return $this; } /** *    err- * @param string $path    err- * @return DaemonPHP */ final public function setErr($path) { $this->_err = $path; return $this; } /** *    , *     chroot   . *       . * @param string $path   chroot- */ final public function setChroot($path) { if (!function_exists('chroot')) { throw new DaemonException('Function chroot() has no. Please update you PHP version.'); } $this->_chrootDir = $path; return $this; } /** *    ,  double fork */ final protected function demonize() { $pid = pcntl_fork(); if ($pid == -1) { throw new DaemonException('Not fork process!'); } else if ($pid) { exit(0); } posix_setsid(); chdir('/'); $pid = pcntl_fork(); if ($pid == -1) { throw new DaemonException('Not double fork process!'); } else if ($pid) { $fpid = fopen($this->_pid, 'wb'); fwrite($fpid, $pid); fclose($fpid); exit(0); } posix_setsid(); chdir('/'); ini_set('error_log', $this->_baseDir . '/php_error.log'); fclose(STDIN); fclose(STDOUT); fclose(STDERR); $STDIN = fopen('/dev/null', 'r'); if ($this->_chrootDir !== null) { chroot($this->_chrootDir); } $STDOUT = fopen($this->_log, 'ab'); if (!is_writable($this->_log)) throw new DaemonException('LOG-file is not writable!'); $STDERR = fopen($this->_err, 'ab'); if (!is_writable($this->_err)) throw new DaemonException('ERR-file is not writable!'); $this->run(); } /** *   PID  * @return int PID  */ final protected function getPID() { if (file_exists($this->_pid)) { $pid = (int) file_get_contents($this->_pid); if (posix_kill($pid, SIG_DFL)) { return $pid; } else { //   ,  PID-  unlink($this->_pid); return 0; } } else { return 0; } } /** *       demonize() */ final public function start() { if (($pid = $this->getPID()) > 0) { echo "Process is running on PID: " . $pid . PHP_EOL; } else { echo "Starting..." . PHP_EOL; $this->demonize(); } } /** *    */ final public function stop() { if (($pid = $this->getPID()) > 0) { echo "Stopping ... "; posix_kill($pid, SIGTERM); unlink($this->_pid); echo "OK" . PHP_EOL; } else { echo "Process not running!" . PHP_EOL; } } /** *      stop()  start() */ final public function restart() { $this->stop(); $this->start(); } /** *     */ final public function status() { if (($pid = $this->getPID()) > 0) { echo "Process is running on PID: " . $pid . PHP_EOL; } else { echo "Process not running!" . PHP_EOL; } } /** *      */ final public function handle($argv) { switch ($argv[1]) { case 'start': $this->start(); break; case 'stop': $this->stop(); break; case 'restart': $this->restart(); break; case 'status': $this->status(); break; default: echo "Unknown command!" . PHP_EOL . "Use: " . $argv[0] . " start|stop|restart|status" . PHP_EOL; break; } } /** *   ,    . *    */ abstract public function run(); } ?>
      
      







コードがあまりにも詳細にコメントアウトされていないことをすぐに謝罪し、修正することを約束します。 これまでのところ、phpdocセクションのみを記述しました。 デーモンを実装するには、 DaemonPHPクラスから継承し、抽象run()メソッドを実装する必要があります。このメソッドでは、デーモンのコードは次のようになります。



 <?php require_once 'daemon.php'; class MyDaemon extends DaemonPHP { public function run() { while (true) { } } } $daemon = new MyDaemon('/tmp/test.pid'); $daemon->setChroot('/home/shaman/work/PHPTest/daemon') //   chroot ->setLog('/my.log') ->setErr('/my.err') // chroot     /home/shaman/work/PHPTest/daemon ->handle($argv); } ?>
      
      







上記のコードを検討してください。 DaemonPHP抽象クラスを継承するMyDaemonクラスを作成しました。 DaemonPHPクラスのすべてのメソッドはfinalとして宣言されますが、1つを除き、これは抽象メソッドrun()です。 このメソッドの本体には、デーモンが実行する必要があるコードが含まれています。 私たちの場合、これは悪魔が働いているのを見るための単なる空の無限ループです。 次に、 MyDaemonクラスの$デーモンオブジェクトを作成しました。絶対パスは、デーモンのPIDファイルが作成されるコンストラクターに渡されます。このパラメーターが渡されない場合、デフォルトでは、PIDファイルはデーモンファイルと同じディレクトリに作成されます-php.pid 次に、 setChroot()メソッドを使用してchrootを実行するようにディレクトリを設定します。これはセキュリティ上の理由からすぐに追加されましたが、これは必要ありません。 ところで、chrootを実行するには、rootからデーモンを実行する必要があるかもしれません。 LOGファイルとERRファイルの絶対パスを以下に示しますこれらのパラメーターが指定されていない場合、 daemon-php.logdaemon-php.errファイルが現在のディレクトリに作成されます。 将来的には、これらすべてのオプションをすぐにコンストラクターに渡すことができるように、コンストラクターを拡張する予定です。 次に、 handle()メソッドを呼び出します。このメソッドに$ argvコマンドライン引数を渡します。 このメソッドは、コマンドライン引数を処理するためのスイッチケースコンストラクトの作成について考えないように特別に作成されています。 ただし、それでも、このメソッドを呼び出すことはできませんが、独自の処理を行うことができます。クラスにはpublicメソッドstart()stop()restart()status()があります。 メソッドの名前自体が語っていますが、実際には、同じ引数がhandle()を取得することが期待されています。



php_error.logファイルが現在のディレクトリに表示される可能性があることに注意してください。PHP自体でエラーが発生した場合にのみ表示され、これらのエラーのログが書き込まれます。

たとえば、 run.phpという名前でコードとともにファイルを保存し、 を実行します。



user@localhost:~$ php run.php start

Starting...

user@localhost:~$








適切なコマンドでステータスを確認できます。



user@localhost:~$ php run.php status

Process is running on PID: 6539








さて、それに応じてデーモンを停止します。



user@localhost:~$ php run.php stop

Stopping ... OK








このクラスの最新のコードは、リポジトリで常に利用可能です(リンクは上にありました)。 それだけです。機能の最終化と追加に関するコメントとアドバイスをお待ちしています。



All Articles