diff --git a/bin/start b/bin/start
index f52dd8b5..6ad3dc2d 100755
--- a/bin/start
+++ b/bin/start
@@ -1,6 +1,23 @@
-#!/usr/bin/env php
-/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ executable=$(which php)
+ else
+ echo 'Cannot find any PHP runtime, please use command `./install-runtime.sh` or install PHP manually!'
+ exit 1
+ fi
+fi
-(new ZM\ConsoleApplication("zhamao-framework"))->initEnv()->run();
+if [ -f "$(pwd)/src/entry.php" ]; then
+ $executable "$(pwd)/src/entry.php" $@
+elif [ -f "$(pwd)/vendor/zhamao/framework/src/entry.php" ]; then
+ $executable "$(pwd)/vendor/zhamao/framework/src/entry.php" $@
+else
+ echo "Cannot find zhamao-framework entry file!"
+ exit 1
+fi
diff --git a/build-runtime.sh b/build-runtime.sh
deleted file mode 100755
index 07d3f31b..00000000
--- a/build-runtime.sh
+++ /dev/null
@@ -1,305 +0,0 @@
-#!/usr/bin/env bash
-
-function downloadIt() {
- downloader="wget"
- type wget >/dev/null 2>&1 || { downloader="curl"; }
- if [ "$downloader" = "wget" ]; then
- _down_prefix="O"
- else
- _down_prefix="o"
- fi
- _down_symbol=0
- if [ ! -f "$2" ]; then
- echo $1
- $downloader "$1" -$_down_prefix "$2" >/dev/null 2>&1 && \
- echo "完成!" && _down_symbol=1
- else
- echo "已存在!" && _down_symbol=1
- fi
- if [ $_down_symbol == 0 ]; then
- echo "失败!请检查网络连接!"
- rm -rf "$2"
- return 1
- fi
- return 0
-}
-
-downloadIt https://mirrors.cloud.tencent.com/openssl/source/ /tmp/openssl_ver.html
-
-_php_ver="7.1.33"
-_libiconv_ver="1.15"
-_openssl_ver=$(cat /tmp/openssl_ver.html | grep "openssl-1.1.1.*.tar.gz<" | awk -F\" '{print $2}' | awk -F- '{print $2}' | awk -F".tar.gz" '{print $1}')
-_swoole_ver="4.6.3"
-_home_dir=$(pwd)"/"
-
-function checkEnv() {
- echo -n "检测核心组件... "
- _msg="请通过包管理安装此依赖!"
- type git >/dev/null 2>&1 || { echo "失败,git 不存在!"$_msg; return 1; }
- type gcc >/dev/null 2>&1 || { echo "失败,gcc 不存在!"$_msg; return 1; }
- type g++ >/dev/null 2>&1 || { echo "失败,g++ 不存在!"$_msg; return 1; }
- type unzip >/dev/null 2>&1 || { echo "失败,unzip 不存在!"$_msg; return 1; }
- type autoconf >/dev/null 2>&1 || { echo "失败,autoconf 不存在!"; return 1; }
- #type pkg-config >/dev/null 2>&1 || { echo "失败,pkg-config 不存在!"$_msg; return 1; }
- type wget >/dev/null 2>&1 || type curl >/dev/null 2>&1 || { echo "失败,curl/wget 不存在!"$_msg; return 1; }
- echo "完成!"
- echo "如果下载过程中出现错误,请删除 runtime/ 文件夹重试!"
- echo "此脚本安装的php/swoole均为最小版本,不含其他扩展(如zip、xml、gd)等!"
- echo -n "如果编译过程缺少依赖,请通过包管理安装对应的依赖![按回车继续] "
- # shellcheck disable=SC2034
- read ents
-}
-
-
-
-function downloadAll() {
- # 创建文件夹
- mkdir "$_home_dir""runtime" >/dev/null 2>&1
- mkdir "$_home_dir""runtime/tmp_download" >/dev/null 2>&1
- mkdir "$_home_dir""runtime/cellar" >/dev/null 2>&1
- _down_dir=$_home_dir"runtime/tmp_download/"
-
- # 下载PHP
- echo -n "正在下载 php 源码... "
- downloadIt "http://mirrors.sohu.com/php/php-$_php_ver.tar.gz" "$_down_dir""php.tar.gz" || { exit; } &
-
- # 下载libiconv
- echo -n "正在下载 libiconv 源码... "
- downloadIt "https://mirrors.tuna.tsinghua.edu.cn/gnu/libiconv/libiconv-$_libiconv_ver.tar.gz" "$_down_dir""libiconv.tar.gz" || { exit; } &
-
- echo -n "正在下载 openssl 源码... "
- downloadIt "http://mirrors.cloud.tencent.com/openssl/source/openssl-$_openssl_ver.tar.gz" "$_down_dir""openssl.tar.gz" || { exit; } &
-
- echo -n "正在下载 swoole 源码... "
- downloadIt "https://dl.zhamao.me/swoole/swoole-$_swoole_ver.tgz" "$_down_dir""swoole.tar.gz" || { exit; } &
-
- echo -n "正在下载 composer ... "
- downloadIt "https://mirrors.aliyun.com/composer/composer.phar" "$_home_dir""runtime/cellar/composer" || { exit; } &
-
- echo -n "正在下载 zlib ... "
- downloadIt "https://zlib.net/fossils/zlib-1.2.5.tar.gz" "$_down_dir""zlib.tar.gz" || { exit; } &
-
- echo -n "正在下载 libxml2 ... "
- downloadIt "https://dl.zhamao.me/libxml2/libxml2-2.9.8.tar.gz" "$_down_dir""libxml2.tar.gz" || { exit; } &
-
- echo -n "正在下载 libpng ... "
- downloadIt "https://dl.zhamao.me/libpng/libpng-1.6.37.tar.gz" "$_down_dir""libpng.tar.gz" || { exit; } &
-
- echo -n "正在下载 oniguruma ... "
- downloadIt "https://dl.zhamao.me/oniguruma/onig-6.9.6.tar.gz" "$_down_dir""onig.tar.gz" || { exit; } &
-
- wait
-
- #echo -n "正在下载 libcurl 源码... "
- #downloadIt "https://curl.se/download/curl-7.75.0.tar.gz" "$_down_dir""libcurl.tar.gz" || { exit; }
-}
-
-function compileIt() {
- _down_dir="$_home_dir""runtime/tmp_download/"
- _source_dir="$_home_dir""runtime/tmp_source/"
- _cellar_dir="$_home_dir""runtime/cellar/"
- case $1 in
- "onig")
- if [ -f "$_cellar_dir""onig/bin/onig-config" ]; then
- echo "已编译!" && return
- fi
- tar -xf "$_down_dir""onig.tar.gz" -C "$_source_dir" && \
- cd "$_source_dir""onig-6.9.6" && \
- ./configure --prefix="$_cellar_dir""onig" && \
- make -j4 && \
- make install && \
- echo "完成!"
- ;;
- "libxml2")
- if [ -f "$_cellar_dir""libxml2/lib/libxml2.so" ]; then
- echo "已编译!" && return
- fi
- tar -xf "$_down_dir""libxml2.tar.gz" -C "$_source_dir" && \
- cd "$_source_dir""libxml2-2.9.8" && \
- ./configure --prefix="$_cellar_dir""libxml2" --exec-prefix="$_cellar_dir""libxml2" --without-python && \
- make -j4 && \
- make install && \
- echo "完成!"
- ;;
- "libpng")
- if [ -f "$_cellar_dir""libpng/bin/libpng-config" ]; then
- echo "已编译!" && return
- fi
- tar -xf "$_down_dir""libpng.tar.gz" -C "$_source_dir" && \
- cd "$_source_dir""libpng-1.6.37" && \
- LDFLAGS="-L$_cellar_dir""zlib/lib" CPPFLAGS="-I$_cellar_dir""zlib/include" ./configure --prefix="$_cellar_dir""libpng" && \
- make -j4 && \
- make install && \
- echo "完成!"
- ;;
- "zlib")
- if [ -f "$_cellar_dir""zlib/lib/libz.so" ]; then
- echo "已编译!" && return
- fi
- tar -xf "$_down_dir""zlib.tar.gz" -C "$_source_dir" && \
- cd "$_source_dir""zlib-1.2.5" && \
- ./configure --prefix="$_cellar_dir""zlib" && \
- make -j4 && \
- make install && \
- echo "完成!"
- ;;
- "libiconv")
- if [ -f "$_cellar_dir""libiconv/bin/iconv" ]; then
- echo "已编译!" && return
- fi
- tar -xf "$_down_dir""libiconv.tar.gz" -C "$_source_dir" && \
- cd "$_source_dir""libiconv-"$_libiconv_ver && \
- ./configure --prefix="$_cellar_dir""libiconv" >/dev/null 2>&1 && \
- make -j4 >/dev/null 2>&1 && \
- make install >/dev/null 2>&1 && \
- echo "完成!"
- ;;
- "libzip")
- if [ -f "$_cellar_dir""libzip/bin/libzip" ]; then
- echo "已编译!" && return
- fi
- tar -xf "$_down_dir""libzip.tar.gz" -C "$_source_dir" && \
- cd "$_source_dir""libzip-1.7.3" && \
- ./configure --prefix="$_cellar_dir""libzip" && \
- make -j4 && \
- make install && \
- echo "完成!"
- ;;
- "libcurl")
- if [ -f "$_cellar_dir""libcurl/bin/libcurl" ]; then
- echo "已编译!" && return
- fi
- tar -xf "$_down_dir""libcurl.tar.gz" -C "$_source_dir" && \
- cd "$_source_dir""libcurl-7.75.0" && \
- ./configure --prefix="$_cellar_dir""libcurl" && \
- make -j4 && \
- make install && \
- echo "完成!"
- ;;
- "php")
- if [ -f "$_cellar_dir""php/bin/php" ]; then
- echo "已编译!" && return
- fi
- PKG_CONFIG_PATH="$_cellar_dir""openssl/lib/pkgconfig"
- PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$_cellar_dir""zlib/lib/pkgconfig"
- PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$_cellar_dir""libxml2/lib/pkgconfig"
- PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$_cellar_dir""libpng/lib/pkgconfig"
- PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$_cellar_dir""onig/lib/pkgconfig"
- tar -xf "$_down_dir""php.tar.gz" -C "$_source_dir" && \
- cd "$_source_dir""php-"$_php_ver && \
- ./buildconf --force && \
- PKG_CONFIG_PATH="$PKG_CONFIG_PATH" ./configure --prefix="$_cellar_dir""php" \
- --with-config-file-path="$_home_dir""runtime/etc" \
- --disable-fpm \
- --enable-cli \
- --enable-posix \
- --enable-ctype \
- --enable-mysqlnd \
- --enable-mbstring \
- --enable-gd \
- --enable-pdo \
- --enable-pcntl \
- --with-openssl="$_cellar_dir""openssl" \
- --enable-sockets \
- --without-sqlite3 \
- --without-pdo-sqlite \
- --with-pdo-mysql=mysqlnd \
- --with-zlib="$_cellar_dir""zlib" \
- --with-iconv="$_cellar_dir""libiconv" \
- --enable-phar && \
- make -j4 && \
- make install && \
- cp "$_source_dir""php-$_php_ver/php.ini-production" "$_home_dir""runtime/etc/php.ini" && \
- echo "完成!"
- ;;
- "openssl")
- if [ -f "$_cellar_dir""openssl/bin/openssl" ]; then
- echo "已编译!" && return
- fi
- tar -xf "$_down_dir""openssl.tar.gz" -C "$_source_dir" && \
- cd "$_source_dir""openssl-""$_openssl_ver" && \
- ./config --prefix="$_cellar_dir""openssl" && \
- make -j4 && \
- make install && \
- echo "完成!"
- ;;
- "swoole")
- "$_home_dir"runtime/cellar/php/bin/php --ri swoole >/dev/null 2>&1
- # shellcheck disable=SC2181
- if [ $? == 0 ]; then
- echo "已编译!" && return
- fi
- tar -xf "$_down_dir""swoole.tar.gz" -C "$_source_dir" && \
- cd "$_source_dir""swoole-""$_swoole_ver" && \
- PATH="$_cellar_dir""php/bin:$PATH" phpize && \
- PATH="$_cellar_dir""php/bin:$PATH" ./configure --prefix="$_cellar_dir""php" \
- --enable-sockets \
- --enable-http2 \
- --enable-openssl \
- --with-openssl-dir="$_cellar_dir""openssl" \
- --enable-mysqlnd && \
- make -j4 && \
- make install && \
- echo "extension=swoole.so" >> "$_home_dir""runtime/etc/php.ini" && \
- echo "完成!"
- ;;
- esac
-}
-
-function compileAll() {
- _down_dir=$_home_dir"runtime/tmp_download/"
- _source_dir=$_home_dir"runtime/tmp_source/"
- mkdir "$_source_dir" >/dev/null 2>&1
- mkdir "$_home_dir""runtime/etc" >/dev/null 2>&1
-
- echo -n "正在编译 libiconv ... "
- compileIt libiconv || { return 1; }
-
- #echo -n "正在编译 libcurl ... "
- #compileIt libcurl || { exit; }
-
- echo -n "正在编译 openssl ... "
- compileIt openssl || { return 1; }
-
- echo -n "正在编译 zlib ... "
- compileIt zlib || { return 1; }
-
- echo -n "正在编译 libxml2 ... "
- compileIt libxml2 || { return 1; }
-
- echo -n "正在编译 libpng ... "
- compileIt libpng || { return 1; }
-
- echo -n "正在编译 oniguruma ... "
- compileIt onig || { return 1; }
-
- #echo -n "正在编译 libzip ... "
- #compileIt libzip || { exit; }
-
- echo -n "正在编译 php ... "
- compileIt php || { return 1; }
-
- echo -n "正在编译 swoole ... "
- compileIt swoole || { return 1; }
-
- return 0
-}
-
-function linkBin(){
- mkdir "$_home_dir""runtime/bin" >/dev/null 2>&1
- ln -s "$_home_dir""runtime/cellar/php/bin/php" "$_home_dir""runtime/bin/php" >/dev/null 2>&1
- echo "runtime/cellar/php/bin/php runtime/cellar/composer \$@" > "$_home_dir""runtime/bin/composer" && chmod +x "$_home_dir""runtime/bin/composer"
- echo "Done!"
- "$_home_dir"runtime/bin/composer config repo.packagist composer https://mirrors.aliyun.com/composer/
-}
-
-checkEnv && \
-downloadAll && \
-compileAll && \
-linkBin && \
-echo "成功部署所有环境!" && \
-echo -e "composer更新依赖:\t\"runtime/bin/composer update\"" && \
-echo -e "启动框架(源码模式):\t\"runtime/bin/php bin/start server\"" && \
-echo -e "启动框架(普通模式):\t\"runtime/bin/php vendor/bin/start server\""
-
-
diff --git a/composer.json b/composer.json
index a5b9e90d..68a47509 100644
--- a/composer.json
+++ b/composer.json
@@ -33,8 +33,7 @@
"zhamao/console": "^1.0.10",
"zhamao/config": "^1.0",
"zhamao/request": "^1.1",
- "zhamao/connection-manager": "^1.0",
- "league/climate": "^3.7"
+ "zhamao/connection-manager": "^1.0"
},
"suggest": {
"ext-ctype": "Use C/C++ extension instead of polyfill will be more efficient",
@@ -45,9 +44,7 @@
},
"autoload": {
"psr-4": {
- "ZM\\": "src/ZM",
- "Module\\": "src/Module",
- "Custom\\": "src/Custom"
+ "ZM\\": "src/ZM"
},
"files": [
"src/ZM/global_functions.php"
@@ -56,4 +53,4 @@
"require-dev": {
"swoole/ide-helper": "@dev"
}
-}
\ No newline at end of file
+}
diff --git a/config/global.php b/config/global.php
index 0441f463..9f334790 100644
--- a/config/global.php
+++ b/config/global.php
@@ -11,11 +11,11 @@ $config['port'] = 20001;
/** 框架开到公网或外部的HTTP访问链接,通过 DataProvider::getFrameworkLink() 获取 */
$config['http_reverse_link'] = "http://127.0.0.1:" . $config['port'];
-/** 框架是否启动debug模式 */
+/** 框架是否启动debug模式,当debug模式为true时,启用热更新(需要安装inotify扩展) */
$config['debug_mode'] = false;
/** 存放框架内文件数据的目录 */
-$config['zm_data'] = realpath(__DIR__ . "/../") . '/zm_data/';
+$config['zm_data'] = realpath(WORKING_DIR) . '/zm_data/';
/** 存放各个模块配置文件的目录 */
$config['config_dir'] = $config['zm_data'] . 'config/';
@@ -107,11 +107,6 @@ $config['static_file_server'] = [
]
];
-/** 注册 Swoole Server 事件注解的类列表 */
-$config['server_event_handler_class'] = [
- // 这里添加例如 \ZM\Event\ServerEventHandler::class 这样的启动注解类
-];
-
/** 机器人解析模块,关闭后无法使用如CQCommand等注解(上面的modules即将废弃) */
$config['onebot'] = [
'status' => true,
diff --git a/docs/component/global-functions.md b/docs/component/global-functions.md
index d90fe552..2566314f 100644
--- a/docs/component/global-functions.md
+++ b/docs/component/global-functions.md
@@ -4,6 +4,8 @@
## getClassPath()
+[源码](https://github.com/zhamao-robot/zhamao-framework/blob/master/src/ZM/global_functions.php#L24)
+
根据加载的用户编写的代码类名来获取类所在的文件路径。
=== "src/Module/Example/Hello.php"
@@ -38,6 +40,8 @@
## explodeMsg()
+[源码](https://github.com/zhamao-robot/zhamao-framework/blob/master/src/ZM/global_functions.php#L39)
+
切割字符串的函数,支持多空格,换行,tab。
定义:`explodeMsg($msg, $ban_comma = false)`
@@ -49,6 +53,8 @@ echo json_encode($s, 128|256); // ["你好啊","你好你好","我还有多个
## unicode_decode()
+[源码](https://github.com/zhamao-robot/zhamao-framework/blob/master/src/ZM/global_functions.php#L54)
+
Unicode 解码,一般用于被转义的 Unicode 转回来。
```php
@@ -57,6 +63,8 @@ echo unicode_decode("\u4f60\u597d"); // 你好
## matchPattern()
+[源码](https://github.com/zhamao-robot/zhamao-framework/blob/master/src/ZM/global_functions.php#L91)
+
根据星号匹配字符串(非正则表达式)。
匹配示例:
@@ -81,6 +89,8 @@ matchPattern("*把*翻译成*", "请把你好翻译成阿拉伯语"); // true
## split_explode()
+[源码](https://github.com/zhamao-robot/zhamao-framework/blob/master/src/ZM/global_functions.php#L103)
+
和 `explodeMsg()` 类似,用作分割字符串,不过此函数加入了对 `中文|数字` 两者的分割,也就是说中文和数字之间也会被分割。
定义:`split_explode($del, $str, $divide_en = false)`
@@ -97,6 +107,8 @@ split_explode(" ", "前进20 急啊急啊"); // ["前进","20","急啊急啊"]
## matchArgs()
+[源码](https://github.com/zhamao-robot/zhamao-framework/blob/master/src/ZM/global_functions.php#L135)
+
`matchPattern()` 的扩展,如果 `matchPattern()` 格式的字符串和模式匹配成功,则通过星号位置来提取星号匹配到的内容,参数同 `matchPattern()`。
```php
diff --git a/ext/go-cqhttp/go-cqhttp-down.sh b/ext/go-cqhttp/go-cqhttp-down.sh
index 846d49e8..4559a90e 100755
--- a/ext/go-cqhttp/go-cqhttp-down.sh
+++ b/ext/go-cqhttp/go-cqhttp-down.sh
@@ -6,6 +6,11 @@ if [ "$(uname -m)" = "x86_64" ]; then
arch_type="amd64"
elif [ "$(uname -m)" = "i386" ]; then
arch_type="386"
+elif [ "$(uname -m)" = "aarch64" ]; then
+ arch_type="arm64"
+else
+ echo "Not supported architecture: $(uname -m)"
+ exit 1
fi
aas=$(uname -s | tr 'A-Z' 'a-z')
diff --git a/install-runtime.sh b/install-runtime.sh
new file mode 100755
index 00000000..f934af1b
--- /dev/null
+++ b/install-runtime.sh
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+
+function download_file() {
+ downloader="wget"
+ type wget >/dev/null 2>&1 || { downloader="curl"; }
+ if [ "$downloader" = "wget" ]; then
+ _down_prefix="O"
+ else
+ _down_prefix="o"
+ fi
+ _down_symbol=0
+ if [ ! -f "$2" ]; then
+ echo $1
+ $downloader "$1" -$_down_prefix "$2" >/dev/null 2>&1 && \
+ echo "完成!" && _down_symbol=1
+ else
+ echo "已存在!" && _down_symbol=1
+ fi
+ if [ $_down_symbol == 0 ]; then
+ echo "失败!请检查网络连接!"
+ rm -rf "$2"
+ return 1
+ fi
+ return 0
+}
+
+function test_composer_and_php() {
+ succ=$("$(pwd)/runtime/composer" -n about | grep Manage)
+ if [ "$succ" = "" ]; then
+ echo "Download PHP binary and composer failed!"
+ return 1
+ fi
+ return 0
+}
+
+mkdir "$(pwd)/runtime" >/dev/null 2>&1
+if [ ! -f "$(pwd)/runtime/php" ]; then
+ download_file "https://dl.zhamao.me/php-bin/down.php?php_ver=7.4&arch=$(uname -m)" "$(pwd)/runtime/php.tar.gz"
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
+ tar -xf "$(pwd)/runtime/php.tar.gz" -C "$(pwd)/runtime/"
+fi
+if [ ! -f "$(pwd)/runtime/composer" ]; then
+ download_file "https://mirrors.aliyun.com/composer/composer.phar" "$(pwd)/runtime/composer.phar"
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
+ echo '$(dirname $0)/php $(dirname $0)/composer.phar $@' > $(pwd)/runtime/composer
+ chmod +x $(pwd)/runtime/composer
+ test_composer_and_php
+fi
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+echo "成功下载!" && \
+ echo -e "PHP使用:\truntime/php -v" && \
+ echo -e "Composer使用:\truntime/composer"
\ No newline at end of file
diff --git a/src/ZM/Command/DaemonReloadCommand.php b/src/ZM/Command/DaemonReloadCommand.php
index 7f17513c..0a5f86f7 100644
--- a/src/ZM/Command/DaemonReloadCommand.php
+++ b/src/ZM/Command/DaemonReloadCommand.php
@@ -3,7 +3,7 @@
namespace ZM\Command;
-use Symfony\Component\Console\Command\Command;
+use Swoole\Process;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -17,7 +17,7 @@ class DaemonReloadCommand extends DaemonCommand
protected function execute(InputInterface $input, OutputInterface $output): int {
parent::execute($input, $output);
- system("kill -USR1 " . intval($this->daemon_file["pid"]));
+ Process::kill(intval($this->daemon_file["pid"]), SIGUSR1);
$output->writeln("成功重载!");
return 0;
}
diff --git a/src/ZM/Command/DaemonStatusCommand.php b/src/ZM/Command/DaemonStatusCommand.php
index d1aee2e4..fb0e19f6 100644
--- a/src/ZM/Command/DaemonStatusCommand.php
+++ b/src/ZM/Command/DaemonStatusCommand.php
@@ -3,7 +3,6 @@
namespace ZM\Command;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
diff --git a/src/ZM/Command/DaemonStopCommand.php b/src/ZM/Command/DaemonStopCommand.php
index ca2ae5d4..933fbc76 100644
--- a/src/ZM/Command/DaemonStopCommand.php
+++ b/src/ZM/Command/DaemonStopCommand.php
@@ -3,7 +3,7 @@
namespace ZM\Command;
-use Symfony\Component\Console\Command\Command;
+use Swoole\Process;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use ZM\Utils\DataProvider;
@@ -18,7 +18,7 @@ class DaemonStopCommand extends DaemonCommand
protected function execute(InputInterface $input, OutputInterface $output): int {
parent::execute($input, $output);
- system("kill -INT " . intval($this->daemon_file["pid"]));
+ Process::kill(intval($this->daemon_file["pid"]), SIGINT);
unlink(DataProvider::getWorkingDir() . "/.daemon_pid");
$output->writeln("成功停止!");
return 0;
diff --git a/src/ZM/Command/InitCommand.php b/src/ZM/Command/InitCommand.php
index 1093e431..6f324758 100644
--- a/src/ZM/Command/InitCommand.php
+++ b/src/ZM/Command/InitCommand.php
@@ -12,6 +12,7 @@ use Symfony\Component\Console\Output\OutputInterface;
class InitCommand extends Command
{
private $extract_files = [
+ "/zhamao",
"/config/global.php",
"/.gitignore",
"/config/file_header.json",
@@ -50,11 +51,6 @@ class InitCommand extends Command
echo "Skipping " . $file . " , file exists." . PHP_EOL;
}
}
- echo "Copying ./zhamao\n";
- file_put_contents(
- $base_path."/zhamao",
- "#!/usr/bin/env php\ninitEnv(\"server\")->run();"
- );
chmod($base_path."/zhamao", 0755);
$autoload = [
"psr-4" => [
diff --git a/src/ZM/Command/RunServerCommand.php b/src/ZM/Command/RunServerCommand.php
index 50971533..6a07cb6e 100644
--- a/src/ZM/Command/RunServerCommand.php
+++ b/src/ZM/Command/RunServerCommand.php
@@ -31,6 +31,8 @@ class RunServerCommand extends Command
new InputOption("watch", null, null, "监听 src/ 目录的文件变化并热更新"),
new InputOption("show-php-ver", null, null, "启动时显示PHP和Swoole版本"),
new InputOption("env", null, InputOption::VALUE_REQUIRED, "设置环境类型 (production, development, staging)"),
+ new InputOption("disable-safe-exit", null, null, "关闭安全退出(关闭后按CtrlC时直接杀死进程)"),
+ new InputOption("preview", null, null, "只显示参数,不启动服务器")
]);
$this->setDescription("Run zhamao-framework | 启动框架");
$this->setHelp("直接运行可以启动");
diff --git a/src/ZM/ConsoleApplication.php b/src/ZM/ConsoleApplication.php
index 1c011e73..61b5c4b3 100644
--- a/src/ZM/ConsoleApplication.php
+++ b/src/ZM/ConsoleApplication.php
@@ -19,8 +19,8 @@ use ZM\Command\SystemdCommand;
class ConsoleApplication extends Application
{
- const VERSION_ID = 406;
- const VERSION = "2.4.5";
+ const VERSION_ID = 407;
+ const VERSION = "2.5.0";
public function __construct(string $name = 'UNKNOWN') {
define("ZM_VERSION_ID", self::VERSION_ID);
diff --git a/src/ZM/Event/SwooleEvent/OnManagerStart.php b/src/ZM/Event/SwooleEvent/OnManagerStart.php
index 240f1233..b65cad5a 100644
--- a/src/ZM/Event/SwooleEvent/OnManagerStart.php
+++ b/src/ZM/Event/SwooleEvent/OnManagerStart.php
@@ -10,6 +10,7 @@ use Swoole\Server;
use ZM\Annotation\Swoole\SwooleHandler;
use ZM\Console\Console;
use ZM\Event\SwooleEvent;
+use ZM\Framework;
/**
* Class OnManagerStart
@@ -19,9 +20,11 @@ use ZM\Event\SwooleEvent;
class OnManagerStart implements SwooleEvent
{
public function onCall(Server $server) {
- pcntl_signal(SIGINT, function () {
- Console::verbose("Interrupted in manager!");
- });
+ if (!Framework::$argv["disable-safe-exit"]) {
+ pcntl_signal(SIGINT, function () {
+ Console::verbose("Interrupted in manager!");
+ });
+ }
Console::verbose("进程 Manager 已启动");
}
}
\ No newline at end of file
diff --git a/src/ZM/Event/SwooleEvent/OnStart.php b/src/ZM/Event/SwooleEvent/OnStart.php
index fa53c229..f3830139 100644
--- a/src/ZM/Event/SwooleEvent/OnStart.php
+++ b/src/ZM/Event/SwooleEvent/OnStart.php
@@ -24,18 +24,20 @@ class OnStart implements SwooleEvent
{
public function onCall(Server $server) {
$r = null;
- Process::signal(SIGINT, function () use ($r, $server) {
- if (zm_atomic("_int_is_reload")->get() === 1) {
- zm_atomic("_int_is_reload")->set(0);
- $server->reload();
- } else {
- echo "\r";
- Console::warning("Server interrupted(SIGINT) on Master.");
- if ((Framework::$server->inotify ?? null) !== null)
- /** @noinspection PhpUndefinedFieldInspection */ Event::del(Framework::$server->inotify);
- Process::kill($server->master_pid, SIGTERM);
- }
- });
+ if (!Framework::$argv["disable-safe-exit"]) {
+ Process::signal(SIGINT, function () use ($r, $server) {
+ if (zm_atomic("_int_is_reload")->get() === 1) {
+ zm_atomic("_int_is_reload")->set(0);
+ $server->reload();
+ } else {
+ echo "\r";
+ Console::warning("Server interrupted(SIGINT) on Master.");
+ if ((Framework::$server->inotify ?? null) !== null)
+ /** @noinspection PhpUndefinedFieldInspection */ Event::del(Framework::$server->inotify);
+ Process::kill($server->master_pid, SIGTERM);
+ }
+ });
+ }
if (Framework::$argv["daemon"]) {
$daemon_data = json_encode([
"pid" => $server->master_pid,
@@ -45,13 +47,13 @@ class OnStart implements SwooleEvent
}
if (Framework::$argv["watch"]) {
if (extension_loaded('inotify')) {
- Console::warning("Enabled File watcher, do not use in production.");
+ Console::info("Enabled File watcher, framework will reload automatically.");
/** @noinspection PhpUndefinedFieldInspection */
Framework::$server->inotify = $fd = inotify_init();
$this->addWatcher(DataProvider::getWorkingDir() . "/src", $fd);
Event::add($fd, function () use ($fd) {
$r = inotify_read($fd);
- dump($r);
+ Console::verbose("File updated: ".$r[0]["name"]);
ZMUtil::reload();
});
} else {
diff --git a/src/ZM/Event/SwooleEvent/OnWorkerStart.php b/src/ZM/Event/SwooleEvent/OnWorkerStart.php
index e58f0933..dc375960 100644
--- a/src/ZM/Event/SwooleEvent/OnWorkerStart.php
+++ b/src/ZM/Event/SwooleEvent/OnWorkerStart.php
@@ -33,7 +33,6 @@ use ZM\Store\MySQL\SqlPoolStorage;
use ZM\Store\Redis\ZMRedisPool;
use ZM\Utils\DataProvider;
use ZM\Utils\ProcessManager;
-use ZM\Utils\ZMUtil;
/**
* Class OnWorkerStart
@@ -43,15 +42,19 @@ use ZM\Utils\ZMUtil;
class OnWorkerStart implements SwooleEvent
{
public function onCall(Server $server, $worker_id) {
- Process::signal(SIGINT, function () use ($worker_id, $server) {
+ if (!Framework::$argv["disable-safe-exit"]) {
+ Process::signal(SIGINT, function () use ($worker_id, $server) {
- });
+ });
+ }
unset(Context::$context[Coroutine::getCid()]);
if ($server->taskworker === false) {
- Process::signal(SIGUSR1, function () use ($worker_id) {
- Timer::clearAll();
- ProcessManager::resumeAllWorkerCoroutines();
- });
+ if (!Framework::$argv["disable-safe-exit"]) {
+ Process::signal(SIGUSR1, function () use ($worker_id) {
+ Timer::clearAll();
+ ProcessManager::resumeAllWorkerCoroutines();
+ });
+ }
zm_atomic("_#worker_" . $worker_id)->set($server->worker_pid);
if (LightCacheInside::get("wait_api", "wait_api") !== null) {
LightCacheInside::unset("wait_api", "wait_api");
@@ -84,7 +87,7 @@ class OnWorkerStart implements SwooleEvent
}
Console::info("新建SQL连接池中");
ob_start();
- phpinfo();
+ phpinfo(); //这个phpinfo是有用的,不能删除
$str = ob_get_clean();
$str = explode("\n", $str);
foreach ($str as $k => $v) {
@@ -130,7 +133,7 @@ class OnWorkerStart implements SwooleEvent
$dispatcher->dispatchEvents($server, $worker_id);
if ($dispatcher->status === EventDispatcher::STATUS_NORMAL) Console::debug("@OnStart 执行完毕");
else Console::warning("@OnStart 执行异常!");
- Console::success("Worker #" . $worker_id . " 已启动");
+ Console::success("Worker #" . $worker_id . " started");
} catch (Exception $e) {
Console::error("Worker加载出错!停止服务!");
Console::error($e->getMessage() . "\n" . $e->getTraceAsString());
@@ -147,7 +150,7 @@ class OnWorkerStart implements SwooleEvent
try {
Framework::$server = $server;
$this->loadAnnotations();
- Console::success("TaskWorker #" . $server->worker_id . " 已启动");
+ Console::success("TaskWorker #" . $server->worker_id . " started");
} catch (Exception $e) {
Console::error("Worker加载出错!停止服务!");
Console::error($e->getMessage() . "\n" . $e->getTraceAsString());
diff --git a/src/ZM/Framework.php b/src/ZM/Framework.php
index 2bf72bbb..a55974fa 100644
--- a/src/ZM/Framework.php
+++ b/src/ZM/Framework.php
@@ -7,6 +7,8 @@ namespace ZM;
use Doctrine\Common\Annotations\AnnotationReader;
use Error;
use Exception;
+use Swoole\Event;
+use Swoole\Process;
use Swoole\Server\Port;
use ZM\Annotation\Swoole\OnSetup;
use ZM\Config\ZMConfig;
@@ -109,6 +111,7 @@ class Framework
$out["environment"] = $args["env"] === null ? "default" : $args["env"];
$out["log_level"] = Console::getLevel();
$out["version"] = ZM_VERSION . (LOAD_MODE == 0 ? (" (build " . ZM_VERSION_ID . ")") : "");
+ $out["master_pid"] = posix_getpid();
if (APP_VERSION !== "unknown") $out["app_version"] = APP_VERSION;
if (isset($this->server_set["task_worker_num"])) {
$out["task_worker"] = $this->server_set["task_worker_num"];
@@ -135,7 +138,9 @@ class Framework
$out["working_dir"] = DataProvider::getWorkingDir();
self::printProps($out, $tty_width, $args["log-theme"] === null);
-
+ if ($args["preview"]) {
+ exit();
+ }
self::$server = new Server(ZMConfig::get("global", "host"), ZMConfig::get("global", "port"));
if ($add_port) {
@@ -297,47 +302,88 @@ class Framework
* @throws ReflectionException
*/
private function registerServerEvents() {
- $event_list = [];
$reader = new AnnotationReader();
-
+ global $master_events;
+ $master_events = [
+ "setup" => [],
+ "event" => []
+ ];
$all = getAllClasses(FRAMEWORK_ROOT_DIR . "/src/ZM/Event/SwooleEvent/", "ZM\\Event\\SwooleEvent");
foreach ($all as $v) {
$class = new $v();
$reflection_class = new ReflectionClass($class);
$anno_class = $reader->getClassAnnotation($reflection_class, SwooleHandler::class);
if ($anno_class !== null) { // 类名形式的注解
- $anno_class->class = $v;
- $anno_class->method = "onCall";
- $event_list[strtolower($anno_class->event)] = $anno_class;
+ $master_events["event"][]=[
+ "class" => $v,
+ "method" => "onCall",
+ "event" => $anno_class->event
+ ];
}
}
- $all_event_class = ZMConfig::get("global", "server_event_handler_class") ?? [];
- foreach ($all_event_class as $v) {
- $reflection_class = new ReflectionClass($v);
- $methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC);
- foreach ($methods as $vs) {
- $method_annotations = $reader->getMethodAnnotations($vs);
- if ($method_annotations != []) {
- $annotation = $method_annotations[0];
- if ($annotation instanceof SwooleHandler) {
- $annotation->class = $v;
- $annotation->method = $vs->getName();
- $event_list[strtolower($annotation->event)] = $annotation;
- } elseif ($annotation instanceof OnSetup) {
- $annotation->class = $v;
- $annotation->method = $vs->getName();
- $c = new $v();
- $m = $annotation->method;
- $c->$m();
+ $base_path = DataProvider::getWorkingDir();
+ $scan_paths = [];
+ $composer = json_decode(file_get_contents(DataProvider::getWorkingDir() . "/composer.json"), true);
+ foreach (($composer["autoload"]["psr-4"] ?? []) as $k => $v) {
+ if (is_dir($base_path."/".$v) && !in_array($v, $composer["extra"]["exclude_annotate"] ?? [])) {
+ $scan_paths[trim($k, "\\")]=realpath($base_path."/".$v);
+ }
+ }
+ $all_event_class = [];
+ foreach($scan_paths as $namespace => $autoload_path) {
+ $all_event_class = array_merge($all_event_class, getAllClasses($autoload_path."/", $namespace));
+ }
+ $process = new Process(function(Process $process) use ($all_event_class) {
+ $reader = new AnnotationReader();
+ $event_list = [];
+ $setup_list = [];
+ foreach ($all_event_class as $v) {
+ $reflection_class = new ReflectionClass($v);
+ $methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC);
+ foreach ($methods as $vs) {
+ $method_annotations = $reader->getMethodAnnotations($vs);
+ if ($method_annotations != []) {
+ $annotation = $method_annotations[0];
+ if ($annotation instanceof SwooleHandler) {
+ $event_list[]=[
+ "class" => $v,
+ "method" => $vs->getName(),
+ "event" => $annotation->event
+ ];
+ } elseif ($annotation instanceof OnSetup) {
+ $setup_list[]=[
+ "class" => $v,
+ "method" => $vs->getName()
+ ];
+ }
}
}
}
+ $sock = $process->exportSocket();
+ $sock->send(json_encode(["setup" => $setup_list, "event" => $event_list]));
+ });
+ $process->start();
+ go(function() use ($process) {
+ $socket = $process->exportSocket();
+ global $master_events;
+ $obj = json_decode($socket->recv(), true);
+ if ($obj["setup"] != []) $master_events["setup"] = array_merge($master_events["setup"], $obj["setup"]);
+ if ($obj["event"] != []) $master_events["event"] = array_merge($master_events["event"], $obj["event"]);
+ });
+ Process::wait(true);
+ Event::wait();
+
+ foreach($master_events["setup"] as $k => $v) {
+ $c = ZMUtil::getModInstance($v["class"]);
+ $method = $v["method"];
+ $c->$method();
}
- foreach ($event_list as $k => $v) {
- $c = ZMUtil::getModInstance($v->class);
- $m = $v->method;
- self::$server->on($k, function (...$param) use ($c, $m) { $c->$m(...$param); });
+
+ foreach ($master_events["event"] as $k => $v) {
+ self::$server->on($v["event"], function (...$param) use ($k, $v) {
+ ZMUtil::getModInstance($v["class"])->{$v["method"]}(...$param);
+ });
}
}
@@ -374,7 +420,8 @@ class Framework
case 'debug-mode':
$coroutine_mode = false;
$terminal_id = null;
- Console::warning("You are in debug mode, do not use in production!");
+ self::$argv["watch"] = true;
+ echo ("* You are in debug mode, do not use in production!\n");
break;
case 'daemon':
$this->server_set["daemonize"] = 1;
diff --git a/src/entry.php b/src/entry.php
new file mode 100644
index 00000000..9dd3cff1
--- /dev/null
+++ b/src/entry.php
@@ -0,0 +1,5 @@
+initEnv()->run();
\ No newline at end of file
diff --git a/zhamao b/zhamao
index 37879438..9dce209a 100755
--- a/zhamao
+++ b/zhamao
@@ -1,4 +1,22 @@
-#!/usr/bin/env php
-initEnv("server")->run();
+#!/bin/sh
+
+if [ -f "$(pwd)/runtime/php" ]; then
+ executable="$(pwd)/runtime/php"
+else
+ which php >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ executable=$(which php)
+ else
+ echo 'Cannot find any PHP runtime, please use command `./install-runtime.sh` or install PHP manually!'
+ exit 1
+ fi
+fi
+
+if [ -f "$(pwd)/src/entry.php" ]; then
+ $executable "$(pwd)/src/entry.php" $@
+elif [ -f "$(pwd)/vendor/zhamao/framework/src/entry.php" ]; then
+ $executable "$(pwd)/vendor/zhamao/framework/src/entry.php" $@
+else
+ echo "Cannot find zhamao-framework entry file!"
+ exit 1
+fi
\ No newline at end of file