zoukankan      html  css  js  c++  java
  • php使用inotify扩展监控文件或目录,如果发生改变,就执行指定命令

    通过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());
    

    演示如下所示:

  • 相关阅读:
    1:4 UI标签和通用标签
    1:3访问 servlet API 的两种方式(request,session等内置对象)
    1 :2 Strust2—Demo
    1:1 Struts2概述
    mysql索引原理与慢查询优化1
    mysql流程控制
    mysql函数
    mysql存储过程
    mysql事务
    mysql触发器
  • 原文地址:https://www.cnblogs.com/jkko123/p/10960439.html
Copyright © 2011-2022 走看看