mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-02 14:25:38 +08:00
update to v2.0.0-b4 version
change global.php config load time and logic set context get server function available more time delete unused comment and @CQAPISend @CQCommand add start_with and end_with set exceptions extended by ZMException rename @SwooleSetup to @ZMSetup fix quotes for global.php fix LightCache empty presistence_path error remove RemoteShell
This commit is contained in:
@@ -3,7 +3,8 @@
|
|||||||
"description": "High performance QQ robot and web server development framework",
|
"description": "High performance QQ robot and web server development framework",
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"version": "2.0.0-b3",
|
"version": "2.0.0-b4",
|
||||||
|
"extra": {},
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "whale",
|
"name": "whale",
|
||||||
@@ -21,30 +22,24 @@
|
|||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2",
|
"php": ">=7.2",
|
||||||
"ext-mbstring": "*",
|
|
||||||
"doctrine/annotations": "~1.10",
|
"doctrine/annotations": "~1.10",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-posix": "*",
|
|
||||||
"ext-ctype": "*",
|
|
||||||
"psy/psysh": "@stable",
|
"psy/psysh": "@stable",
|
||||||
|
"symfony/polyfill-ctype": "^1.20",
|
||||||
|
"symfony/polyfill-mbstring": "^1.20",
|
||||||
"symfony/console": "^5.1",
|
"symfony/console": "^5.1",
|
||||||
"symfony/polyfill-ctype": "^1.18",
|
|
||||||
"zhamao/connection-manager": "*@dev",
|
"zhamao/connection-manager": "*@dev",
|
||||||
"zhamao/console": "*@dev",
|
"zhamao/console": "*@dev",
|
||||||
"zhamao/config": "*@dev",
|
"zhamao/config": "*@dev",
|
||||||
"zhamao/request": "*@dev",
|
"zhamao/request": "*@dev",
|
||||||
"symfony/routing": "^5.1"
|
"symfony/routing": "^5.1",
|
||||||
},
|
"symfony/polyfill-php80": "^1.20"
|
||||||
"suggest": {
|
|
||||||
"ext-pdo": "Allows framework connecting with mysql server",
|
|
||||||
"ext-redis": "Allows framework connecting with redis server",
|
|
||||||
"ext-inotify": "Enable file watcher feature in framework"
|
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Custom\\": "src/Custom",
|
|
||||||
"ZM\\": "src/ZM",
|
"ZM\\": "src/ZM",
|
||||||
"Module\\": "src/Module"
|
"Module\\": "src/Module",
|
||||||
|
"Custom\\": "src/Custom"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"src/ZM/global_functions.php"
|
"src/ZM/global_functions.php"
|
||||||
@@ -61,11 +56,5 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^9.3",
|
"phpunit/phpunit": "^9.3",
|
||||||
"swoole/ide-helper": "@dev"
|
"swoole/ide-helper": "@dev"
|
||||||
},
|
}
|
||||||
"repositories": [
|
}
|
||||||
{
|
|
||||||
"type": "path",
|
|
||||||
"url": "/Users/jerry/project/git-project/zhamao-console"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -36,10 +36,10 @@ $config['swoole'] = [
|
|||||||
|
|
||||||
/** 轻量字符串缓存,默认开启 */
|
/** 轻量字符串缓存,默认开启 */
|
||||||
$config['light_cache'] = [
|
$config['light_cache'] = [
|
||||||
"size" => 1024, //最多允许储存的条数(需要2的倍数)
|
'size' => 1024, //最多允许储存的条数(需要2的倍数)
|
||||||
"max_strlen" => 16384, //单行字符串最大长度(需要2的倍数)
|
'max_strlen' => 16384, //单行字符串最大长度(需要2的倍数)
|
||||||
"hash_conflict_proportion" => 0.6, //Hash冲突率(越大越好,但是需要的内存更多)
|
'hash_conflict_proportion' => 0.6, //Hash冲突率(越大越好,但是需要的内存更多)
|
||||||
"persistence_path" => $config['zm_data']."_cache.json",
|
'persistence_path' => $config['zm_data'].'_cache.json',
|
||||||
'auto_save_interval' => 900
|
'auto_save_interval' => 900
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ trait CQAPI
|
|||||||
public function processWebsocketAPI($connection, $reply, $function = false) {
|
public function processWebsocketAPI($connection, $reply, $function = false) {
|
||||||
$api_id = ZMAtomic::get("wait_msg_id")->add(1);
|
$api_id = ZMAtomic::get("wait_msg_id")->add(1);
|
||||||
$reply["echo"] = $api_id;
|
$reply["echo"] = $api_id;
|
||||||
//EventHandler::callCQAPISend($reply, $connection);
|
|
||||||
SpinLock::lock("wait_api");
|
SpinLock::lock("wait_api");
|
||||||
$r = LightCacheInside::get("wait_api", "wait_api");
|
$r = LightCacheInside::get("wait_api", "wait_api");
|
||||||
$r[$api_id] = [
|
$r[$api_id] = [
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
|
|
||||||
namespace ZM\Annotation\CQ;
|
|
||||||
|
|
||||||
use Doctrine\Common\Annotations\Annotation\Target;
|
|
||||||
use ZM\Annotation\AnnotationBase;
|
|
||||||
use ZM\Annotation\Interfaces\Level;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class CQAPISend
|
|
||||||
* @package ZM\Annotation\CQ
|
|
||||||
* @Annotation
|
|
||||||
* @Target("METHOD")
|
|
||||||
*/
|
|
||||||
class CQAPISend extends AnnotationBase implements Level
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $action = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
public $with_result = false;
|
|
||||||
|
|
||||||
public $level = 20;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getLevel() {
|
|
||||||
return $this->level;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $level
|
|
||||||
*/
|
|
||||||
public function setLevel($level) {
|
|
||||||
$this->level = $level;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,6 +21,10 @@ class CQCommand extends AnnotationBase implements Level
|
|||||||
public $pattern = "";
|
public $pattern = "";
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $regex = "";
|
public $regex = "";
|
||||||
|
/** @var string */
|
||||||
|
public $start_with = "";
|
||||||
|
/** @var string */
|
||||||
|
public $end_with = "";
|
||||||
/** @var string[] */
|
/** @var string[] */
|
||||||
public $alias = [];
|
public $alias = [];
|
||||||
/** @var string */
|
/** @var string */
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ use Doctrine\Common\Annotations\Annotation\Target;
|
|||||||
use ZM\Annotation\AnnotationBase;
|
use ZM\Annotation\AnnotationBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SwooleSetup
|
* Class ZMSetup
|
||||||
* @package ZM\Annotation\Swoole
|
* @package ZM\Annotation\Swoole
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("METHOD")
|
* @Target("METHOD")
|
||||||
*/
|
*/
|
||||||
class SwooleSetup extends AnnotationBase
|
class ZMSetup extends AnnotationBase
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ class RunServerCommand extends Command
|
|||||||
// ... put here the code to run in your command
|
// ... put here the code to run in your command
|
||||||
// this method must return an integer number with the "exit status code"
|
// this method must return an integer number with the "exit status code"
|
||||||
// of the command. You can also use these constants to make code more readable
|
// of the command. You can also use these constants to make code more readable
|
||||||
new Framework($input->getOptions());
|
(new Framework($input->getOptions()))->start();
|
||||||
// return this if there was no problem running the command
|
// return this if there was no problem running the command
|
||||||
// (it's equivalent to returning int(0))
|
// (it's equivalent to returning int(0))
|
||||||
return Command::SUCCESS;
|
return Command::SUCCESS;
|
||||||
|
|||||||
@@ -18,18 +18,16 @@ use ZM\Utils\DataProvider;
|
|||||||
|
|
||||||
class ConsoleApplication extends Application
|
class ConsoleApplication extends Application
|
||||||
{
|
{
|
||||||
public function __construct(string $name = 'UNKNOWN') {
|
public function __construct(string $name = 'UNKNOWN')
|
||||||
|
{
|
||||||
$version = json_decode(file_get_contents(__DIR__ . "/../../composer.json"), true)["version"] ?? "UNKNOWN";
|
$version = json_decode(file_get_contents(__DIR__ . "/../../composer.json"), true)["version"] ?? "UNKNOWN";
|
||||||
parent::__construct($name, $version);
|
parent::__construct($name, $version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function initEnv() {
|
public function initEnv()
|
||||||
|
{
|
||||||
$this->selfCheck();
|
$this->selfCheck();
|
||||||
$this->addCommands([
|
|
||||||
new RunServerCommand(), //运行主服务的指令控制器
|
|
||||||
new InitCommand(), //初始化用的,用于项目初始化和phar初始化
|
|
||||||
new PureHttpCommand()
|
|
||||||
]);
|
|
||||||
//if (LOAD_MODE === 0) $this->add(new BuildCommand()); //只有在git源码模式才能使用打包指令
|
//if (LOAD_MODE === 0) $this->add(new BuildCommand()); //只有在git源码模式才能使用打包指令
|
||||||
if (LOAD_MODE === 0) define("WORKING_DIR", getcwd());
|
if (LOAD_MODE === 0) define("WORKING_DIR", getcwd());
|
||||||
elseif (LOAD_MODE == 1) define("WORKING_DIR", realpath(__DIR__ . "/../../"));
|
elseif (LOAD_MODE == 1) define("WORKING_DIR", realpath(__DIR__ . "/../../"));
|
||||||
@@ -47,20 +45,49 @@ class ConsoleApplication extends Application
|
|||||||
* @noinspection RedundantSuppression
|
* @noinspection RedundantSuppression
|
||||||
*/
|
*/
|
||||||
require_once WORKING_DIR . "/vendor/autoload.php";
|
require_once WORKING_DIR . "/vendor/autoload.php";
|
||||||
|
echo "* This is repository mode.\n";
|
||||||
|
$composer = json_decode(file_get_contents(DataProvider::getWorkingDir() . "/composer.json"), true);
|
||||||
|
if (!isset($composer["autoload"]["psr-4"]["Module\\"])) {
|
||||||
|
echo "框架源码模式需要在autoload文件中添加Module目录为自动加载,是否添加?[Y/n] ";
|
||||||
|
$r = strtolower(trim(fgets(STDIN)));
|
||||||
|
if ($r === "" || $r === "y") {
|
||||||
|
$composer["autoload"]["psr-4"]["Module\\"] = "src/Module";
|
||||||
|
$composer["autoload"]["psr-4"]["Custom\\"] = "src/Custom";
|
||||||
|
$r = file_put_contents(DataProvider::getWorkingDir() . "/composer.json", json_encode($composer, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
||||||
|
if ($r !== false) {
|
||||||
|
echo "成功添加!请重新进行 composer update !\n";
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
echo "添加失败!请按任意键继续!";
|
||||||
|
fgets(STDIN);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_dir(DataProvider::getWorkingDir() . '/src/')) {
|
if (!is_dir(DataProvider::getWorkingDir() . '/src/')) {
|
||||||
die("Unable to find source directory.\nMaybe you need to run \"init\"?");
|
die("Unable to find source directory.\nMaybe you need to run \"init\"?");
|
||||||
}
|
}
|
||||||
ZMConfig::setDirectory(DataProvider::getWorkingDir().'/config');
|
ZMConfig::setDirectory(DataProvider::getWorkingDir() . '/config');
|
||||||
ZMConfig::env($args["env"] ?? "");
|
ZMConfig::env($args["env"] ?? "");
|
||||||
if(ZMConfig::get("global") === false) die("Global config load failed: ".ZMConfig::$last_error);
|
if (ZMConfig::get("global") === false) {
|
||||||
|
echo ("Global config load failed: " . ZMConfig::$last_error."\nPlease init first!\n");
|
||||||
$command_register = ZMConfig::get("global", "command_register_class") ?? [];
|
$this->add(new InitCommand());
|
||||||
foreach($command_register as $v) {
|
} else {
|
||||||
$obj = new $v();
|
$this->addCommands([
|
||||||
if(!($obj instanceof Command)) throw new TypeError("Command register class must be extended by Symfony\\Component\\Console\\Command\\Command");
|
new RunServerCommand(), //运行主服务的指令控制器
|
||||||
$this->add($obj);
|
new InitCommand(), //初始化用的,用于项目初始化和phar初始化
|
||||||
|
new PureHttpCommand() //纯HTTP服务器指令
|
||||||
|
]);
|
||||||
|
$command_register = ZMConfig::get("global", "command_register_class") ?? [];
|
||||||
|
foreach ($command_register as $v) {
|
||||||
|
$obj = new $v();
|
||||||
|
if (!($obj instanceof Command)) throw new TypeError("Command register class must be extended by Symfony\\Component\\Console\\Command\\Command");
|
||||||
|
$this->add($obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +96,8 @@ class ConsoleApplication extends Application
|
|||||||
* @param OutputInterface|null $output
|
* @param OutputInterface|null $output
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function run(InputInterface $input = null, OutputInterface $output = null) {
|
public function run(InputInterface $input = null, OutputInterface $output = null)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
return parent::run($input, $output);
|
return parent::run($input, $output);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
@@ -77,12 +105,13 @@ class ConsoleApplication extends Application
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function selfCheck() {
|
private function selfCheck()
|
||||||
if (!extension_loaded("swoole")) die("Can not find swoole extension.\n");
|
{
|
||||||
|
if (!extension_loaded("swoole")) die("Can not find swoole extension.\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/19");
|
||||||
if (version_compare(SWOOLE_VERSION, "4.4.13") == -1) die("You must install swoole version >= 4.4.13 !");
|
if (version_compare(SWOOLE_VERSION, "4.4.13") == -1) die("You must install swoole version >= 4.4.13 !");
|
||||||
//if (!extension_loaded("gd")) die("Can not find gd extension.\n");
|
//if (!extension_loaded("gd")) die("Can not find gd extension.\n");
|
||||||
if (!extension_loaded("sockets")) die("Can not find sockets extension.\n");
|
//if (!extension_loaded("sockets")) die("Can not find sockets extension.\n");
|
||||||
if (substr(PHP_VERSION, 0, 1) != "7") die("PHP >=7 required.\n");
|
if (substr(PHP_VERSION, 0, 1) < "7") die("PHP >=7 required.\n");
|
||||||
//if (!function_exists("curl_exec")) die("Can not find curl extension.\n");
|
//if (!function_exists("curl_exec")) die("Can not find curl extension.\n");
|
||||||
//if (!class_exists("ZipArchive")) die("Can not find Zip extension.\n");
|
//if (!class_exists("ZipArchive")) die("Can not find Zip extension.\n");
|
||||||
//if (!file_exists(CRASH_DIR . "last_error.log")) die("Can not find log file.\n");
|
//if (!file_exists(CRASH_DIR . "last_error.log")) die("Can not find log file.\n");
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class Context implements ContextInterface
|
|||||||
/**
|
/**
|
||||||
* @return swoole_server|null
|
* @return swoole_server|null
|
||||||
*/
|
*/
|
||||||
public function getServer() { return self::$context[$this->cid]["server"] ?? null; }
|
public function getServer() { return self::$context[$this->cid]["server"] ?? server(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Frame|null
|
* @return Frame|null
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace ZM\Exception;
|
|||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
class DbException extends Exception
|
class DbException extends ZMException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@ namespace ZM\Exception;
|
|||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
class InterruptException extends Exception
|
class InterruptException extends ZMException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace ZM\Exception;
|
|||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
class InvalidArgumentException extends Exception
|
class InvalidArgumentException extends ZMException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@ namespace ZM\Exception;
|
|||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
class NotInitializedException extends Exception
|
class NotInitializedException extends ZMException
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use Throwable;
|
|||||||
* @package ZM\Exception
|
* @package ZM\Exception
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
class RobotNotFoundException extends Exception
|
class RobotNotFoundException extends ZMException
|
||||||
{
|
{
|
||||||
public function __construct($message = "", $code = 0, Throwable $previous = null) {
|
public function __construct($message = "", $code = 0, Throwable $previous = null) {
|
||||||
parent::__construct($message, $code, $previous);
|
parent::__construct($message, $code, $previous);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace ZM\Exception;
|
|||||||
use Exception;
|
use Exception;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class WaitTimeoutException extends Exception
|
class WaitTimeoutException extends ZMException
|
||||||
{
|
{
|
||||||
public $module;
|
public $module;
|
||||||
|
|
||||||
|
|||||||
12
src/ZM/Exception/ZMException.php
Normal file
12
src/ZM/Exception/ZMException.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace ZM\Exception;
|
||||||
|
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class ZMException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ namespace ZM;
|
|||||||
|
|
||||||
use Doctrine\Common\Annotations\AnnotationReader;
|
use Doctrine\Common\Annotations\AnnotationReader;
|
||||||
use Exception;
|
use Exception;
|
||||||
use ZM\Annotation\Swoole\SwooleSetup;
|
use ZM\Annotation\Swoole\ZMSetup;
|
||||||
use ZM\Config\ZMConfig;
|
use ZM\Config\ZMConfig;
|
||||||
use ZM\ConnectionManager\ManagerGM;
|
use ZM\ConnectionManager\ManagerGM;
|
||||||
use ZM\Event\ServerEventHandler;
|
use ZM\Event\ServerEventHandler;
|
||||||
@@ -15,7 +15,6 @@ use ZM\Store\LightCacheInside;
|
|||||||
use ZM\Store\Lock\SpinLock;
|
use ZM\Store\Lock\SpinLock;
|
||||||
use ZM\Store\ZMAtomic;
|
use ZM\Store\ZMAtomic;
|
||||||
use ZM\Utils\DataProvider;
|
use ZM\Utils\DataProvider;
|
||||||
use Framework\RemoteShell;
|
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
use ReflectionException;
|
use ReflectionException;
|
||||||
use ReflectionMethod;
|
use ReflectionMethod;
|
||||||
@@ -112,16 +111,15 @@ class Framework
|
|||||||
// 注册 Swoole Server 的事件
|
// 注册 Swoole Server 的事件
|
||||||
$this->registerServerEvents();
|
$this->registerServerEvents();
|
||||||
$r = ZMConfig::get("global", "light_cache") ?? [
|
$r = ZMConfig::get("global", "light_cache") ?? [
|
||||||
"size" => 1024,
|
"size" => 1024,
|
||||||
"max_strlen" => 8192,
|
"max_strlen" => 8192,
|
||||||
"hash_conflict_proportion" => 0.6,
|
"hash_conflict_proportion" => 0.6,
|
||||||
"persistence_path" => realpath(DataProvider::getDataFolder() . "_cache.json"),
|
"persistence_path" => realpath(DataProvider::getDataFolder() . "_cache.json"),
|
||||||
"auto_save_interval" => 900
|
"auto_save_interval" => 900
|
||||||
];
|
];
|
||||||
LightCache::init($r);
|
LightCache::init($r);
|
||||||
LightCacheInside::init();
|
LightCacheInside::init();
|
||||||
SpinLock::init($r["size"]);
|
SpinLock::init($r["size"]);
|
||||||
self::$server->start();
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Console::error("Framework初始化出现错误,请检查!");
|
Console::error("Framework初始化出现错误,请检查!");
|
||||||
Console::error($e->getMessage());
|
Console::error($e->getMessage());
|
||||||
@@ -129,6 +127,10 @@ class Framework
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function start() {
|
||||||
|
self::$server->start();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从全局配置文件里读取注入系统事件的类
|
* 从全局配置文件里读取注入系统事件的类
|
||||||
* @throws ReflectionException
|
* @throws ReflectionException
|
||||||
@@ -152,7 +154,7 @@ class Framework
|
|||||||
$annotation->class = $v;
|
$annotation->class = $v;
|
||||||
$annotation->method = $vs->getName();
|
$annotation->method = $vs->getName();
|
||||||
$event_list[strtolower($annotation->event)] = $annotation;
|
$event_list[strtolower($annotation->event)] = $annotation;
|
||||||
} elseif ($annotation instanceof SwooleSetup) {
|
} elseif ($annotation instanceof ZMSetup) {
|
||||||
$annotation->class = $v;
|
$annotation->class = $v;
|
||||||
$annotation->method = $vs->getName();
|
$annotation->method = $vs->getName();
|
||||||
$c = new $v();
|
$c = new $v();
|
||||||
@@ -213,14 +215,6 @@ class Framework
|
|||||||
case 'disable-console-input':
|
case 'disable-console-input':
|
||||||
if ($y) $terminal_id = null;
|
if ($y) $terminal_id = null;
|
||||||
break;
|
break;
|
||||||
case 'remote-shell':
|
|
||||||
if ($y) {
|
|
||||||
$host = "127.0.0.1";
|
|
||||||
$port = 9599;
|
|
||||||
RemoteShell::listen(self::$server, $host, $port);
|
|
||||||
Console::log(Console::setColor("正在监听" . $host . ":" . strval($port) . "的调试接口,请注意安全", "yellow"));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'log-error':
|
case 'log-error':
|
||||||
if ($y) Console::setLevel(0);
|
if ($y) Console::setLevel(0);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -88,7 +88,13 @@ class QQBot
|
|||||||
if(($word[0] != "" && $v->match == $word[0]) || in_array($word[0], $v->alias)) {
|
if(($word[0] != "" && $v->match == $word[0]) || in_array($word[0], $v->alias)) {
|
||||||
ctx()->setCache("match", $word);
|
ctx()->setCache("match", $word);
|
||||||
return true;
|
return true;
|
||||||
} elseif ($v->pattern != "") {
|
} elseif ($v->start_with != "" && mb_strpos(ctx()->getMessage(), $v->start_with) === 0) {
|
||||||
|
ctx()->setCache("match", [mb_substr(ctx()->getMessage(), mb_strlen($v->start_with))]);
|
||||||
|
return true;
|
||||||
|
} elseif ($v->end_with != "" && strlen(ctx()->getMessage()) == (strripos(ctx()->getMessage(), $v->end_with) + strlen($v->end_with))) {
|
||||||
|
ctx()->setCache("match", [substr(ctx()->getMessage(), 0, strripos(ctx()->getMessage(), $v->end_with))]);
|
||||||
|
return true;
|
||||||
|
}elseif ($v->pattern != "") {
|
||||||
$match = matchArgs($v->pattern, ctx()->getMessage());
|
$match = matchArgs($v->pattern, ctx()->getMessage());
|
||||||
if($match !== false) {
|
if($match !== false) {
|
||||||
ctx()->setCache("match", $match);
|
ctx()->setCache("match", $match);
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ class LightCache
|
|||||||
$r[$k] = self::parseGet($v);
|
$r[$k] = self::parseGet($v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(self::$config["persistence_path"] == "") return;
|
||||||
$r = file_put_contents(self::$config["persistence_path"], json_encode($r, 128 | 256));
|
$r = file_put_contents(self::$config["persistence_path"], json_encode($r, 128 | 256));
|
||||||
if ($r === false) Console::error("Not saved, please check your \"persistence_path\"!");
|
if ($r === false) Console::error("Not saved, please check your \"persistence_path\"!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,263 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
|
|
||||||
namespace Framework;
|
|
||||||
|
|
||||||
|
|
||||||
use Co;
|
|
||||||
use Exception;
|
|
||||||
use Swoole\Coroutine;
|
|
||||||
use swoole\server;
|
|
||||||
|
|
||||||
class RemoteShell
|
|
||||||
{
|
|
||||||
const STX = "DEBUG";
|
|
||||||
private static $contexts = array();
|
|
||||||
static $oriPipeMessageCallback = null;
|
|
||||||
/**
|
|
||||||
* @var server
|
|
||||||
*/
|
|
||||||
static $serv;
|
|
||||||
static $menu = array(
|
|
||||||
"p|print [variant]\t打印一个PHP变量的值",
|
|
||||||
"e|exec [code]\t执行一段PHP代码",
|
|
||||||
"w|worker [id]\t切换Worker进程",
|
|
||||||
"l|list\t打印服务器所有连接的fd",
|
|
||||||
"s|stats\t打印服务器状态",
|
|
||||||
"c|coros\t打印协程列表",
|
|
||||||
"b|bt\t打印协程调用栈",
|
|
||||||
"i|info [fd]\t显示某个连接的信息",
|
|
||||||
"h|help\t显示帮助界面",
|
|
||||||
"q|quit\t退出终端",
|
|
||||||
);
|
|
||||||
const PAGESIZE = 20;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $serv server
|
|
||||||
* @param string $host
|
|
||||||
* @param int $port
|
|
||||||
* @throws Exception
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
static function listen($serv, $host = "127.0.0.1", $port = 9599) {
|
|
||||||
$port = $serv->listen($host, $port, SWOOLE_SOCK_TCP);
|
|
||||||
if (!$port) {
|
|
||||||
throw new Exception("listen fail.");
|
|
||||||
}
|
|
||||||
$port->set(array(
|
|
||||||
"open_eof_split" => true,
|
|
||||||
'package_eof' => "\r\n",
|
|
||||||
));
|
|
||||||
$port->on("Connect", array(__CLASS__, 'onConnect'));
|
|
||||||
$port->on("Close", array(__CLASS__, 'onClose'));
|
|
||||||
$port->on("Receive", array(__CLASS__, 'onReceive'));
|
|
||||||
if (method_exists($serv, 'getCallback')) {
|
|
||||||
self::$oriPipeMessageCallback = $serv->getCallback('PipeMessage');
|
|
||||||
}
|
|
||||||
$serv->on("PipeMessage", array(__CLASS__, 'onPipeMessage'));
|
|
||||||
self::$serv = $serv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function onConnect($serv, $fd, $reactor_id) {
|
|
||||||
self::$contexts[$fd]['worker_id'] = $serv->worker_id;
|
|
||||||
self::output($fd, implode("\r\n", self::$menu));
|
|
||||||
}
|
|
||||||
|
|
||||||
static function output($fd, $msg) {
|
|
||||||
if (!isset(self::$contexts[$fd]['worker_id'])) {
|
|
||||||
$msg .= "\r\nworker#" . self::$serv->worker_id . "$ ";
|
|
||||||
} else {
|
|
||||||
$msg .= "\r\nworker#" . self::$contexts[$fd]['worker_id'] . "$ ";
|
|
||||||
}
|
|
||||||
self::$serv->send($fd, $msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function onClose($serv, $fd, $reactor_id) {
|
|
||||||
unset(self::$contexts[$fd]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function onPipeMessage($serv, $src_worker_id, $message) {
|
|
||||||
//不是 debug 消息
|
|
||||||
if (!is_string($message) or substr($message, 0, strlen(self::STX)) != self::STX) {
|
|
||||||
if (self::$oriPipeMessageCallback == null) {
|
|
||||||
trigger_error("require swoole-4.3.0 or later.", E_USER_WARNING);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return call_user_func(self::$oriPipeMessageCallback, $serv, $src_worker_id, $message);
|
|
||||||
} else {
|
|
||||||
$request = unserialize(substr($message, strlen(self::STX)));
|
|
||||||
self::call($request['fd'], $request['func'], $request['args']);
|
|
||||||
}
|
|
||||||
return true ;
|
|
||||||
}
|
|
||||||
|
|
||||||
static protected function call($fd, $func, $args) {
|
|
||||||
ob_start();
|
|
||||||
call_user_func_array($func, $args);
|
|
||||||
self::output($fd, ob_get_clean());
|
|
||||||
}
|
|
||||||
|
|
||||||
static protected function exec($fd, $func, $args) {
|
|
||||||
//不在当前Worker进程
|
|
||||||
if (self::$contexts[$fd]['worker_id'] != self::$serv->worker_id) {
|
|
||||||
self::$serv->sendMessage(self::STX . serialize(['fd' => $fd, 'func' => $func, 'args' => $args]), self::$contexts[$fd]['worker_id']);
|
|
||||||
} else {
|
|
||||||
self::call($fd, $func, $args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static function getCoros() {
|
|
||||||
var_export(iterator_to_array(Coroutine::listCoroutines()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static function getBackTrace($_cid) {
|
|
||||||
$info = Co::getBackTrace($_cid);
|
|
||||||
if (!$info) {
|
|
||||||
echo "coroutine $_cid not found.";
|
|
||||||
} else {
|
|
||||||
echo get_debug_print_backtrace($info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static function printVariant($var) {
|
|
||||||
$var = ltrim($var, '$ ');
|
|
||||||
var_dump($var);
|
|
||||||
var_dump($$var);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function evalCode($code) {
|
|
||||||
eval($code . ';');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $serv server
|
|
||||||
* @param $fd
|
|
||||||
* @param $reactor_id
|
|
||||||
* @param $data
|
|
||||||
*/
|
|
||||||
static function onReceive($serv, $fd, $reactor_id, $data) {
|
|
||||||
$args = explode(" ", $data, 2);
|
|
||||||
$cmd = trim($args[0]);
|
|
||||||
unset($args[0]);
|
|
||||||
switch ($cmd) {
|
|
||||||
case 'w':
|
|
||||||
case 'worker':
|
|
||||||
if (!isset($args[1])) {
|
|
||||||
self::output($fd, "invalid command.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$dstWorkerId = intval($args[1]);
|
|
||||||
self::$contexts[$fd]['worker_id'] = $dstWorkerId;
|
|
||||||
self::output($fd, "[switching to worker " . self::$contexts[$fd]['worker_id'] . "]");
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
case 'exec':
|
|
||||||
if (!isset($args[1])) {
|
|
||||||
self::output($fd, "invalid command.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$var = trim($args[1]);
|
|
||||||
self::exec($fd, 'self::evalCode', [$var]);
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
case 'print':
|
|
||||||
$var = trim($args[1]);
|
|
||||||
self::exec($fd, 'self::printVariant', [$var]);
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
case 'help':
|
|
||||||
self::output($fd, implode("\r\n", self::$menu));
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
case 'stats':
|
|
||||||
$stats = $serv->stats();
|
|
||||||
self::output($fd, var_export($stats, true));
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
case 'coros':
|
|
||||||
self::exec($fd, 'self::getCoros', []);
|
|
||||||
break;
|
|
||||||
/**
|
|
||||||
* 查看协程堆栈
|
|
||||||
*/
|
|
||||||
case 'bt':
|
|
||||||
case 'b':
|
|
||||||
case 'backtrace':
|
|
||||||
if (empty($args[1])) {
|
|
||||||
self::output($fd, "invalid command [" . trim($args[1]) . "].");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$_cid = intval($args[1]);
|
|
||||||
self::exec($fd, 'self::getBackTrace', [$_cid]);
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
case 'info':
|
|
||||||
if (empty($args[1])) {
|
|
||||||
self::output($fd, "invalid command [" . trim($args[1]) . "].");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$_fd = intval($args[1]);
|
|
||||||
$info = $serv->getClientInfo($_fd);
|
|
||||||
if (!$info) {
|
|
||||||
self::output($fd, "connection $_fd not found.");
|
|
||||||
} else {
|
|
||||||
self::output($fd, var_export($info, true));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
case 'list':
|
|
||||||
$tmp = array();
|
|
||||||
foreach ($serv->connections as $fd) {
|
|
||||||
$tmp[] = $fd;
|
|
||||||
if (count($tmp) > self::PAGESIZE) {
|
|
||||||
self::output($fd, json_encode($tmp));
|
|
||||||
$tmp = array();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (count($tmp) > 0) {
|
|
||||||
self::output($fd, json_encode($tmp));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'q':
|
|
||||||
case 'quit':
|
|
||||||
$serv->close($fd);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
self::output($fd, "unknow command[$cmd]");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_debug_print_backtrace($traces) {
|
|
||||||
$ret = array();
|
|
||||||
foreach ($traces as $i => $call) {
|
|
||||||
$object = '';
|
|
||||||
if (isset($call['class'])) {
|
|
||||||
$object = $call['class'] . $call['type'];
|
|
||||||
if (is_array($call['args'])) {
|
|
||||||
foreach ($call['args'] as &$arg) {
|
|
||||||
get_arg($arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$ret[] = '#' . str_pad($i, 3, ' ')
|
|
||||||
. $object . $call['function'] . '(' . implode(', ', $call['args'])
|
|
||||||
. ') called at [' . $call['file'] . ':' . $call['line'] . ']';
|
|
||||||
}
|
|
||||||
return implode("\n", $ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_arg(&$arg) {
|
|
||||||
if (is_object($arg)) {
|
|
||||||
$arr = (array)$arg;
|
|
||||||
$args = array();
|
|
||||||
foreach ($arr as $key => $value) {
|
|
||||||
if (strpos($key, chr(0)) !== false) {
|
|
||||||
$key = ''; // Private variable found
|
|
||||||
}
|
|
||||||
$args[] = '[' . $key . '] => ' . get_arg($value);
|
|
||||||
}
|
|
||||||
$arg = get_class($arg) . ' Object (' . implode(',', $args) . ')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -40,6 +40,7 @@ class ZMUtil
|
|||||||
foreach (server()->connections as $v) {
|
foreach (server()->connections as $v) {
|
||||||
server()->close($v);
|
server()->close($v);
|
||||||
}
|
}
|
||||||
|
LightCache::savePersistence();
|
||||||
//DataProvider::saveBuffer();
|
//DataProvider::saveBuffer();
|
||||||
Timer::clearAll();
|
Timer::clearAll();
|
||||||
server()->reload();
|
server()->reload();
|
||||||
|
|||||||
Reference in New Issue
Block a user