mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-21 15:45:36 +08:00
update to build 407
change daemon command from system to Process::kill add master_pid for motd information add option --preview delete server_event_handler_class and use process go-cqhttp-down.sh script add arm64 support add ./zhamao support change build-runtime.sh to install-runtime.sh add option --disable-safe-exit adjust some Console output set start script using /bin/sh for supporting auto searching php and framework
This commit is contained in:
@@ -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("<info>成功重载!</info>");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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("<info>成功停止!</info>");
|
||||
return 0;
|
||||
|
||||
@@ -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\n<?php require_once \"vendor/autoload.php\";(new ZM\ConsoleApplication(\"zhamao-framework\"))->initEnv(\"server\")->run();"
|
||||
);
|
||||
chmod($base_path."/zhamao", 0755);
|
||||
$autoload = [
|
||||
"psr-4" => [
|
||||
|
||||
@@ -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("直接运行可以启动");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 已启动");
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
5
src/entry.php
Normal file
5
src/entry.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php /** @noinspection PhpIncludeInspection */
|
||||
|
||||
require_once ((!is_dir(__DIR__ . '/../vendor')) ? getcwd() : (__DIR__ . "/..")) . "/vendor/autoload.php";
|
||||
|
||||
(new ZM\ConsoleApplication("zhamao-framework"))->initEnv()->run();
|
||||
Reference in New Issue
Block a user