設定パターン2
/etc/init.d/iasrecompd
等を作っていい感じに。
/recompile.phpがアパッチ上でリコンパイルをするようにします。
あとは、ファイルを書き換えたりしてみればうまくいったり行かなかったりします。
うまく行かない場合はコマンドライン上でinotifyapcsmartyrecompiler.phpを実行してみて問題をつぶしましょう。
ソースそのままだと、smartyが動かないと思うので適当にincludeかrequireしてください。
excludesには監視対象から省く正規表現を書くことが出来ます。
あと、ほかに監視して何かしたい場合はgetPatternとexecute($file,$m)メソッドを持ったクラスを作って登録すれば動くので
いろいろ拡張できます。
ファイルをアップしたら、変換するプログラムとかアンなことやこんなこともと夢が広がります。
<?php class Inotify { var $files; var $excludes; var $actions; function __construct($params) { $this->files = $params['files']; $this->excludes = $params['excludes']; $this->actions = $params['actions']; $this->watches = array(); $this->settings = array(); } function run() { // 自動フラッシュをオン ob_implicit_flush(1); if (!extension_loaded('inotify')) { fprintf(STDERR, "Inotify extension not loaded !\n"); exit(1); } $this->inotify = inotify_init(); if ($this->inotify === false) { fprintf(STDERR, "Failed to obtain an inotify instance\n"); return 1; } foreach($this->files as $file) { // 再帰的ディレクトリ登録 $rc = $this->addWatch($file); if ($rc != 0) return $rc; } $rc = $this->main_loop(); // May not happen inotify_rm_watch($this->inotify, $watch); fclose($this->inotify); return $rc; } function addWatch($file) { foreach($this->excludes as $exclude) { if (strpos($file, $exclude) !== false) return 0; } if (isset($this->settings[$file])) return 0; echo "add ".$file; $watch = inotify_add_watch($this->inotify, $file, IN_MODIFY| IN_ATTRIB | IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVE_FROM| IN_MOVE_TO | IN_MOVE | IN_DONT_FOLLOW | IN_ONLYDIR); $this->watches[$watch]=$file; $this->settings[$file]=true; echo " $watch\n"; if ($watch === false) { fprintf(STDERR, "Failed to watch file '%s'", $file); return 1; } if (!is_dir($file)) { break; } $dir = opendir($file); while($f = readdir($dir)) { if ($f == ".." || $f == ".") continue; $fname = $file.$f."/"; if (is_dir($fname)) { $this->settings[] = $fname; $rc = $this->addWatch($fname); if ($rc != 0) return $rc; } } closedir($dir); return 0; } function main_loop() { // 変化のあったファイルを格納する配列 $actionFiles = array(); // イベントループ while (($events = inotify_read($this->inotify)) !== false) { // イベントをすべて処理 foreach($events as $event) { // ファイル名を取得 $file = $this->watches[$event['wd']] . $event['name']; // ファイルを省く foreach($this->excludes as $exclude) { if (strpos($file, $exclude) !== false) continue 2; } if (is_dir($file)) { // ディレクトリ追加 $this->addWatch($file."/"); } else { // アクションファイルに追加 $actionFiles[$file] = $file; } } // 300msほど待ち usleep (300000); if (inotify_queue_len($this->inotify)>0) { // キューにまだデータがある場合はここまで continue; } // 溜め込んだファイルのアクションを実行 foreach($actionFiles as $file) { // 登録してあるアクションでループ foreach($this->actions as $action) { // アクションにマッチ $m = array(); if (preg_match($action->getPattern(), $file, $m)) { // アクション実行 $action->execute($file, $m); } } } // アクションファイルの初期化 $actionFiles = array(); } return 0; } } /** * phpのapcのリコンパイラ */ class PHPAPCReCompileAction { /** * phpのファイルにマッチする正規表現 */ function getPattern() { return "/\\.php$/"; } /** * ファイルをコンパイルして、失敗したらキャッシュをすべて消す */ function execute($file, $m) { /* echo "compile $file\n"; if(apc_compile_file($file)===false){ echo "compile $file error\n"; apc_clear_cache(); // 出来れば、コンパイルしたファイルだけ削除したいけど出来ない。。。 }*/ // リコンパイルだけはapacheでやる file_get_contents("http://localhost/recompile.php?passfraze=dhfsryewqnvdkl70hbjly81djfs4y8319fhjdks1eup&filename=".$file); } } /** * Smartyのテンプレートアクション */ class SmartyTemplateAction { /** * コンストラクタ */ function __construct($smarty) { $this->smarty = $smarty; } /** * Smartyのテンプレートにマッチする正規表現 */ function getPattern() { $htmlt = "/". str_replace("/","\\/",$this->smarty->template_dir)."\\/(.+\\.html|.+\\.tpl)$/"; return $htmlt; } /** * コンパイルされたファイルを削除 */ function execute($file, $m) { echo "remove {$m[1]}\n"; $this->smarty->clear_compiled_tpl($m[1]); } } $smarty = new Smarty(); $smarty->template_dir = APP_DIR.'/templates/template'; $smarty->compile_dir = APP_DIR.'/templates/templates_c'; $inotify = new Inotify(array( "files" => array( dirname(dirname(__FILE__))."/html/", dirname(dirname(__FILE__))."/php/", ), "excludes" => array( "/logs/", ), "actions"=> array( new PHPAPCReCompileAction(), new SmartyTemplateAction($smarty), ), )); $inotify->run(); ?>
recompile.php
<?php if($_REQUEST["passfraze"]!="dhfsryewqnvdkl70hbjly81djfs4y8319fhjdks1eup") exit(0); if($_REQUEST["filename"]) { if (apc_compile_file($_REQUEST["filename"])===false){ apc_clear_cache(); } }