forked from donjan-deng/la-user-center
-
Notifications
You must be signed in to change notification settings - Fork 0
/
watch
131 lines (131 loc) · 3.81 KB
/
watch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env php
<?php declare(strict_types=1);
/**
* Hyperf Watch Hot Reload Scripts
* User: [email protected]
* Date: 2019/10/10
* Time: 下午17:30
* Modify From https://github.com/leocavalcante/dwoole/blob/master/dev/watch.php
*/
# PHP Bin File PHP程序所在路径(默认自动获取)
const PHP_BIN_FILE = 'which php';
# Watch Dir 监听目录(默认监听脚本所在的根目录)
const WATCH_DIR = __DIR__ . '/';
# Watch Ext 监听扩展名(多个可用英文逗号隔开)
const WATCH_EXT = 'php,env';
# Exclude Dir 排除目录(不监听的目录,数组形式)
const EXCLUDE_DIR = ['vendor'];
# Entry Point File 入口文件
const ENTRY_POINT_FILE = './bin/hyperf.php';
# Scan Interval 扫描间隔(毫秒,默认2000)
const SCAN_INTERVAL = 2000;
if (!function_exists('exec')) {
echo "[x] 请取消禁用exec函数" . PHP_EOL;
exit(1);
}
define('PHP', PHP_BIN_FILE == 'which php' ? exec('which php') : PHP_BIN_FILE);
if (!file_exists(PHP)) {
echo "[x] PHP bin (" . PHP . ") 没有找到,请确认路径正确?" . PHP_EOL;
exit(1);
}
if (!file_exists(ENTRY_POINT_FILE)) {
echo "[x] 入口文件 (" . ENTRY_POINT_FILE . ") 没有找到,请确认文件存在?" . PHP_EOL;
exit(1);
}
use Swoole\Process;
use Swoole\Timer;
use Swoole\Event;
swoole_async_set(['enable_coroutine' => false]);
$hashes = [];
$serve = null;
echo "🚀 Start @ " . date('Y-m-d H:i:s') . PHP_EOL;
start();
state();
Timer::tick(SCAN_INTERVAL, 'watch');
function start()
{
global $serve;
$serve = new Process('serve', true);
$serve->start();
if (false === $serve->pid) {
echo swoole_strerror(swoole_errno()) . PHP_EOL;
exit(1);
}
Event::add($serve->pipe, function ($pipe) use (&$serve) {
$message = @$serve->read();
if (!empty($message)) {
echo $message;
}
});
}
function watch()
{
global $hashes;
foreach ($hashes as $pathname => $current_hash) {
if (!file_exists($pathname)) {
unset($hashes[$pathname]);
continue;
}
$new_hash = file_hash($pathname);
if ($new_hash != $current_hash) {
change();
state();
break;
}
}
}
function state()
{
global $hashes;
$files = php_files(WATCH_DIR);
$hashes = array_combine($files, array_map('file_hash', $files));
$count = count($hashes);
echo "📡 Watching $count files..." . PHP_EOL;
}
function change()
{
global $serve;
echo "🔄 Restart @ " . date('Y-m-d H:i:s') . PHP_EOL;
Process::kill($serve->pid);
start();
}
function serve(Process $serve)
{
$opt = getopt('c');
if (isset($opt['c'])) echo exec(PHP . ' ' . ENTRY_POINT_FILE . ' di:init-proxy') . '..' . PHP_EOL;
$serve->exec(PHP, [ENTRY_POINT_FILE, 'start']);
}
function file_hash(string $pathname): string
{
$contents = file_get_contents($pathname);
if (false === $contents) {
return 'deleted';
}
return md5($contents);
}
function php_files(string $dirname): array
{
$directory = new RecursiveDirectoryIterator($dirname);
$filter = new Filter($directory);
$iterator = new RecursiveIteratorIterator($filter);
return array_map(function ($fileInfo) {
return $fileInfo->getPathname();
}, iterator_to_array($iterator));
}
class Filter extends RecursiveFilterIterator
{
public function accept()
{
if ($this->current()->isDir()) {
if (preg_match('/^\./', $this->current()->getFilename())) {
return false;
}
return !in_array($this->current()->getFilename(), EXCLUDE_DIR);
}
$list = array_map(function (string $item): string {
return "\.$item";
}, explode(',', WATCH_EXT));
$list = implode('|', $list);
return preg_match("/($list)$/", $this->current()->getFilename());
}
}