From 88bba6eba36a761873a0904ea1a82a4c98eb0558 Mon Sep 17 00:00:00 2001 From: ak Date: Wed, 12 Aug 2026 01:54:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BC=80=E5=8F=91=E6=9C=9F=20workerman?= =?UTF-8?q?=20=E7=83=AD=E9=87=8D=E8=BD=BD=E8=84=9A=E6=9C=AC=EF=BC=88dev:wa?= =?UTF-8?q?tch=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - scripts/dev-watch.sh:优先 fswatch(brew install fswatch),未安装自动回退 PHP 轮询;监听 app/plugins/routes/config/.env 的 php/json 变化 → 自动 workerman:serve restart - scripts/dev-watch.php:纯 PHP mtime 轮询兜底(跨平台,零依赖) - composer 增加 dev:watch 命令 - 实测:touch 配置触发自动重启,新代码生效;生产仍用 restart 手动部署 --- composer.json | 3 +++ scripts/dev-watch.php | 63 +++++++++++++++++++++++++++++++++++++++++++ scripts/dev-watch.sh | 27 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 scripts/dev-watch.php create mode 100755 scripts/dev-watch.sh diff --git a/composer.json b/composer.json index 844cef1..dba39e7 100644 --- a/composer.json +++ b/composer.json @@ -70,6 +70,9 @@ "@php artisan config:clear --ansi", "@php artisan test" ], + "dev:watch": [ + "bash scripts/dev-watch.sh" + ], "post-autoload-dump": [ "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", "@php artisan package:discover --ansi", diff --git a/scripts/dev-watch.php b/scripts/dev-watch.php new file mode 100644 index 0000000..fc41b14 --- /dev/null +++ b/scripts/dev-watch.php @@ -0,0 +1,63 @@ + 重启 workerman。 +// 生产环境无需此脚本,改代码后手动 php artisan workerman:serve restart 即可。 + +$root = dirname(__DIR__); +$dirs = ['app', 'plugins', 'routes', 'config']; +$extraFiles = ['.env']; +$interval = 1; // 秒 + +function snapshot(array $dirs, array $extraFiles, string $root): array +{ + $state = []; + + foreach ($dirs as $dir) { + $path = $root.'/'.$dir; + + if (! is_dir($path)) { + continue; + } + + $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)); + + foreach ($it as $file) { + if (in_array($file->getExtension(), ['php', 'json'], true)) { + $state[$file->getPathname()] = $file->getMTime(); + } + } + } + + foreach ($extraFiles as $file) { + $path = $root.'/'.$file; + + if (is_file($path)) { + $state[$path] = filemtime($path); + } + } + + ksort($state); + + return $state; +} + +function restartWorkerman(string $root): void +{ + echo '['.date('H:i:s').'] 检测到代码变更,重启 workerman:serve...'.PHP_EOL; + passthru('cd '.escapeshellarg($root).' && php artisan workerman:serve restart'); +} + +echo '[watch] 开始监听(PHP 轮询 '.$interval.'s):'.implode(' ', $dirs).' .env'.PHP_EOL; +$prev = snapshot($dirs, $extraFiles, $root); + +while (true) { + sleep($interval); + $current = snapshot($dirs, $extraFiles, $root); + + if ($current !== $prev) { + restartWorkerman($root); + $prev = snapshot($dirs, $extraFiles, $root); + } +} diff --git a/scripts/dev-watch.sh b/scripts/dev-watch.sh new file mode 100755 index 0000000..8b83379 --- /dev/null +++ b/scripts/dev-watch.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# 开发期热重载:监听代码目录变化,自动重启 workerman:serve。 +# 优先用 fswatch(brew install fswatch),未安装时回退纯 PHP 轮询。 +# 用法:php artisan dev:watch 或 bash scripts/dev-watch.sh +set -euo pipefail +cd "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +WATCH_DIRS=(app plugins routes config) +WATCH_FILES=(.env) +WATCH_PATTERN='\.(php|json)$' + +restart() { + echo "[$(date +%H:%M:%S)] 检测到代码变更,重启 workerman:serve..." + php artisan workerman:serve restart +} + +if command -v fswatch >/dev/null 2>&1; then + echo "使用 fswatch 监听:${WATCH_DIRS[*]} ${WATCH_FILES[*]}(Ctrl+C 退出)" + args=() + for d in "${WATCH_DIRS[@]}"; do [ -d "$d" ] && args+=("$d"); done + for f in "${WATCH_FILES[@]}"; do [ -f "$f" ] && args+=("$f"); done + fswatch -0 -l 1 -r --include "$WATCH_PATTERN" --exclude '.*' "${args[@]}" \ + | while IFS= read -r -d '' _; do restart; done +else + echo "未安装 fswatch(brew install fswatch 可升级体验),使用 PHP 轮询兜底..." + php scripts/dev-watch.php +fi