hyperf框架热更新

PHP框架hyperf是cli方式执行,所以文件更改后需kill掉进程,再重新启动才能生效,但在Windows中开发,非常繁琐,本文记录关于hyperf框架的更改文件后自动重启的折腾之路。

首先说明开发环境,桌面环境为Windows,PHP运行环境在WSL中,开发工具为PHPstorm,我需要达到的目的是在Windows中更改项目文件后,hyperf会自动重启。

一、WSL直接监听Windows中项目目录文件

1、首先在WSL中安装inotify,用来监听文件变动。

apt-get install -y inotify-tools

2、添加监听文件变动的shell脚本,脚本暂时命名为hyperf_test_kill.sh

#!/bin/sh
# 监控排除.idea/runtime目录/.log/.swp文件
inotifywait -rq --exclude "(^.+.[^php]$)" -e modify /mnt/e/hyperf_test | while read LINE
do
  kill -9 $(ps -ef | grep hyperf_test | grep -v grep | awk '{print $2}');

这个shell脚本是用来监听Windows中E盘下hyperf_test文件夹的变更,如果有变更,则kill掉项目进程
3、添加启动脚本,脚本暂时命名为hyperf_test__start.sh

#!/bin/sh
# 清除缓存
rm -rf /mnt/e/hyperf_test/runtime/container;
# 启动进程
php8.1 /mnt/e/hyperf_test/bin/hyperf.php start;

这个脚本是用来启动进程

4、安装supervisor常驻任务守护进程

apt-get install -y supervisor

5、添加常驻任务脚本
进入/etc/supervisor/conf.d/目录

添加hyperf_test_kill.conf

# kill hyperf_test进程

[program:hyperf_test_kill]

directory=/root

# 注意脚本路径

command=sh /root/hyperf_test_kill.sh

autostart=true

autorestart=true

startsecs=1

startretries=50

redirect_stderr=true

stdout_logfile=/var/log/supervisor/hyperf_test_kill.log

user=root

stdout_logfile_backups = 20

 

添加hyperf_test_start.conf

# 启动hyperf_test进程

[program:hyperf_test_start]

directory=/root

command=sh /root/message_start.sh

autostart=true

autorestart=true

startsecs=1

startretries=50

redirect_stderr=true

stdout_logfile=/var/log/supervisor/hyperf_test_start.log

user=root

stdout_logfile_backups = 20

 

添加完重新加载supervisor任务即可

但是这种发放在后来莫名其妙的不可用了,WSL中的inotify无法监听Windows的文件变更了,挂载磁盘也不行。

二、直接把项目克隆到WSL系统中

无法监听Windows后,另辟蹊径,直接把项目挪到WSL系统中,因为inotify只是无法监听Windows的文件变更,还是可以继续监听WSL系统的,并且kill进程和重启进程都很快。
但随之而来的问题是,在Windows中访问WSL文件太慢了,尤其是使用PHPstorm时,加载文件、读取索引等操作很是频繁,git切换分支也受到效率影响。

三、PHPstorm监听+inotify监听

在Windows中添加update.bat文件:

@echo off

REM 启动WSL并执行Linux shell脚本

wsl sh /root/update.sh

REM 执行完毕后关闭命令提示符窗口

exit

在WSL中/root目录下新增update.sh文件

#!/bin/sh
echo "$(date '+%Y-%m-%d %H:%M:%S') - Updating log" >> /root/update.log;

hyperf_test_kill.sh脚本变更为:

#!/bin/sh
# 监控/root/update.log文件的变更

inotifywait -q -e modify /root/update.log | while read LINE
do
  kill -9 $(ps -ef | grep bm_message | grep -v grep | awk '{print $2}');
done;

PHPstorm配置:

这套方法的逻辑是,在PHPstorm中使用File Watcher,文件保存时执行update.bat文件,update.bat会执行wsl sh /root/update.sh命令,而update.sh会往/root/update.log追加一条日志,使/root/update.log文件产生变动,inotify再监听update.log重启进程

四、终极解决办法

虽然过去两三年中一直在用hyperf和TP做开发,但一般都忙于开发业务,框架基本用法熟悉之后很少再看文档了。最近有个hyperf后台项目要做,使用的扩展包不兼容最新版的hyperf,需要修改的东西比较多,参考文档的地方比较多,无意中发现hyperf竟然早就支持热更新。
如果是基于swoole的hyperf框架,则直接使用hyperf/watcher包即可。
安装:composer require hyperf/watcher --dev
添加配置:php bin/hyperf.php vendor:publish hyperf/watcher
启动:php bin/hyperf.php server:watch

在wsl中,可以使用supervisor进行守护进程:
[program:hyperf-skeleton-watch]
directory=/data/www/hyperf-skeleton
command=php bin/hyperf.php server:watch
autostart=true
autorestart=true
startsecs=1
startretries=50
redirect_stderr=true
stdout_logfile=/var/log/supervisor/hyperf-skeleton-watch.log
user=root
stdout_logfile_backups = 20

但如果使用的是swow的hyperf框架就比较麻烦了,只能使用buexplain/go-watch来进行热更新。这是一个golang的工具,所以必须先安装golang环境。

在wsl中安装好golang环境之后依次执行以下命令:

cd /data/www
git clone https://github.com/buexplain/go-watch.git
cd go-watch
CGO_ENABLED=0 go build -o gowatch main.go

然后执行./gowatch run -h,出现帮助说明,即为安装成功。
启动:
./gowatch run\
--preCmdIgnoreError=true\
--cmd "php"\
--args "-d extension=/usr/lib/php/20210902/swow.so, /mnt/e/dev/hyperf-swow-watch/bin/hyperf.php, start"\
--files "/mnt/e/dev/hyperf-swow-watch/.env"\
--folder "/mnt/e/dev/hyperf-swow-watch/app/, /mnt/e/dev/hyperf-swow-watch/config/"\
--autoRestart=true

此处对应的原始的php命令为php -d extension=/usr/lib/php/20210902/swow.so /mnt/e/dev/hyperf-swow-watch/bin/hyperf.php start

同样,我们在wsl中,可以使用supervisor进行守护进程:

[program:hyperf-swow-watch]
directory=/data/www/go-watch
command=/bin/bash -c './gowatch run --preCmdIgnoreError=true --cmd "php" --args "-d extension=/usr/lib/php/20210902/swow.so, /mnt/e/dev/hyperf-swow-watch/bin/hyperf.php, start" --files "/mnt/e/dev/hyperf-swow-watch/.env" --folder "/mnt/e/dev/hyperf-swow-watch/app/, /mnt/e/dev/hyperf-swow-watch/config/" --autoRestart=true'
autostart=true
autorestart=true
startsecs=1
startretries=50
redirect_stderr=true
stdout_logfile=/var/log/supervisor/hyperf-swow-watch.log
user=root
stdout_logfile_backups = 20

评论