? <PHP class Monitor { public $ the dir = ''; public $ cmd = ''; public $ timeout =. 1; public function the __construct () { IF (! extension_loaded ( 'inotify')) { echo 'install inotify extension' , value is PHP_EOL; Exit; } // parse command line parameters, a: represents a number required $ = the opts the getopt ( '', [ 'the dir:', 'cmd:']); IF (! $ the opts) { echo 'parameter input error', value is PHP_EOL; Exit; } IF (empty (the opts $ [ 'the dir'])) { echo 'is required --dir', value is PHP_EOL; Exit; } if (empty($opts['cmd'])) { Echo '--cmd is mandatory', PHP_EOL; Exit; } $ this-> the opts the dir = $ [ 'the dir']; $ this-> cmd = TRIM (the opts $ [ 'cmd']); $ this-> RUN (); } // the directory monitor public RUN function () { $ dirs = $ this-> getDirs (this- $> the dir); IF (empty ($ dirs)) { return to false; } $ FD = inotify_init (); // Sets the nonblocking mode stream_set_blocking ( $ FD, 0); the foreach ($ dirs AS $ the dir) { $ Watch = inotify_add_watch ($ FD, $ the dir, as IN_MODIFY | the IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_CLOSE_WRITE); exit; if (!$watch) { echo "{$ dir} add monitoring error", value is PHP_EOL; } } the while (to true) { $ the reads = [$ FD]; $ Write = []; $ the except = []; IF (stream_select ($ the reads, $ Write, the except $, $ this-> timeout)> 0) { ! IF (empty (the reads $)) { the foreach ($ $ Read the reads AS) { // file changes $ = fileChg to false; // change directory $ dirChg = false; // read the data stream read from $ = inotify_read Events ($ read); $ fileName = ''; the foreach (AS $ $ Events Event) { $ fileName = $ Event [ 'name']; Switch ($ Event [ 'mask']) { Case the IN_CREATE: Case IN_DELETE: $ fileChg = to true; BREAK; Case 1,073,742,080: Case 1,073,742,336: $ dirChg = to true; BREAK; } } if ($fileChg) { echo "file {$ fileName} changed, performed $ this- command {>} cmd ", value is PHP_EOL; echo shell_exec ($ this-> cmd), value is PHP_EOL; } IF ($ dirChg) { echo "{$ fileName} directory changes, Run {$ this-> cmd}", value is PHP_EOL; echo shell_exec ($ this-> cmd), value is PHP_EOL; return $ this-> RUN (); } } } } } return to true; } accessories subdirectory path to the current directory // recursive public function getDirs ($ dir ) { $ The realpath the dir = ($ the dir); $ DH = the opendir ($ the dir); ! IF ($ DH) { return []; } $ dirs = []; $ dirs [] = $ the 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());