通过inotify扩展监控文件或目录的变化,如果发生变化,就执行命令。
可以应用于 swoole 中,如果文件发生变化,就执行 kill -USR1 进程PID 来实现热更新。
<?php class Monitor { public $dir = ''; public $cmd = ''; public $timeout = 1; public function __construct() { if (!extension_loaded('inotify')) { echo '请安装inotify扩展', PHP_EOL; exit; } //解析命令行参数,有一个:号表示必填项 $opts = getopt('', ['dir:', 'cmd:']); if (!$opts) { echo '参数输入错误', PHP_EOL; exit; } if (empty($opts['dir'])) { echo '--dir 是必填项', PHP_EOL; exit; } if (empty($opts['cmd'])) { echo '--cmd 是必填项', PHP_EOL; exit; } $this->dir = $opts['dir']; $this->cmd = trim($opts['cmd']); $this->run(); } //对目录进行监控 public function run() { $dirs = $this->getDirs($this->dir); if (empty($dirs)) { return false; } $fd = inotify_init(); //设置为非阻塞模式 stream_set_blocking($fd, 0); foreach ($dirs as $dir) { $watch = inotify_add_watch($fd, $dir, IN_MODIFY | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_CLOSE_WRITE); if (!$watch) { echo "{$dir} 添加监控错误", PHP_EOL; exit; } } while (true) { $reads = [$fd]; $write = []; $except = []; if (stream_select($reads, $write, $except, $this->timeout) > 0) { if (!empty($reads)) { foreach ($reads as $read) { //文件改变 $fileChg = false; //目录改变 $dirChg = false; //从可读流中读取数据 $events = inotify_read($read); $fileName = ''; foreach ($events as $event) { $fileName = $event['name']; switch ($event['mask']) { case IN_CREATE: case IN_DELETE: $fileChg = true; break; case 1073742080: case 1073742336: $dirChg = true; break; } } if ($fileChg) { echo "文件 {$fileName} 发生改变, 执行命令 {$this->cmd}", PHP_EOL; echo shell_exec($this->cmd), PHP_EOL; } if ($dirChg) { echo "目录 {$fileName} 发生改变, 执行命令 {$this->cmd}", PHP_EOL; echo shell_exec($this->cmd), PHP_EOL; return $this->run(); } } } } } return true; } //递归的获取当前目录下所有子目录路径 public function getDirs($dir) { $dir = realpath($dir); $dh = opendir($dir); if (!$dh) { return []; } $dirs = []; $dirs[] = $dir; while (($file = readdir($dh)) !== false) { if ($file == '.' || $file == '..') { continue; } $full = $dir . DIRECTORY_SEPARATOR . $file; if (is_dir($full)) { $dirs = array_merge($dirs, $this->getDirs($full)); } } closedir($dh); return $dirs; } } (new Monitor());
演示如下所示:
版权声明:博主文章,可以不经博主允许随意转载,随意修改,知识是用来传播的。