Merge pull request #131 from zhamao-robot/refactor-framework-entry

轻量重构 Framework 类
This commit is contained in:
sunxyw
2022-05-24 14:36:35 +08:00
committed by GitHub
3 changed files with 278 additions and 244 deletions

View File

@@ -8,11 +8,16 @@ use ZM\Logger\ConsoleLogger;
return [ return [
'level' => LogLevel::DEBUG, 'level' => LogLevel::DEBUG,
'logger' => static function (): LoggerInterface { 'logger' => static function (string $title = null): LoggerInterface {
$worker_id = app('worker_id'); if ($title) {
$title = strtoupper($title);
} else {
// 在 Master 中worker_id 将不存在
$title = app()->has('worker_id') ? '#' . app('worker_id') : 'MST';
}
$logger = new ConsoleLogger(zm_config('logging.level')); $logger = new ConsoleLogger(zm_config('logging.level'));
$logger::$format = "[%date%] [%level%] [#{$worker_id}] %body%"; $logger::$format = "[%date%] [%level%] [{$title}] %body%";
$logger::$date_format = 'Y-m-d H:i:s'; $logger::$date_format = 'Y-m-d H:i:s';
// 如果你喜欢旧版的日志格式,请取消下行注释 // 如果你喜欢旧版的日志格式,请取消下行注释
// $logger::$date_format = 'm-d H:i:s'; // $logger::$date_format = 'm-d H:i:s';

View File

@@ -7,6 +7,7 @@ namespace ZM;
use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\AnnotationReader;
use Error; use Error;
use Exception; use Exception;
use InvalidArgumentException;
use Phar; use Phar;
use ReflectionClass; use ReflectionClass;
use ReflectionException; use ReflectionException;
@@ -118,7 +119,7 @@ class Framework
], ],
]); ]);
} catch (ConnectionManager\TableException $e) { } catch (ConnectionManager\TableException $e) {
echo zm_internal_errcode('E00008') . $e->getMessage() . PHP_EOL; logger()->emergency(zm_internal_errcode('E00008') . $e->getMessage());
exit(1); exit(1);
} }
@@ -144,7 +145,7 @@ class Framework
$this->swoole_server_config['log_level'] = SWOOLE_LOG_DEBUG; $this->swoole_server_config['log_level'] = SWOOLE_LOG_DEBUG;
// 是否启用远程终端 // 是否启用远程终端
$add_port = ZMConfig::get('global', 'remote_terminal')['status'] ?? false; $remote_terminal = ZMConfig::get('global', 'remote_terminal')['status'] ?? false;
// 加载服务器事件 // 加载服务器事件
if (!$instant_mode) { if (!$instant_mode) {
@@ -152,7 +153,7 @@ class Framework
} }
// 解析命令行参数 // 解析命令行参数
$coroutine_mode = $this->parseCliArgs(self::$argv, $add_port); [$coroutine_mode, $terminal_id, $remote_terminal] = $this->parseCliArgs(self::$argv, compact('remote_terminal'));
// 设置默认最长等待时间 // 设置默认最长等待时间
if (!isset($this->swoole_server_config['max_wait_time'])) { if (!isset($this->swoole_server_config['max_wait_time'])) {
@@ -167,57 +168,7 @@ class Framework
// 非静默模式下打印启动信息 // 非静默模式下打印启动信息
if (!self::$argv['private-mode']) { if (!self::$argv['private-mode']) {
$out['working_dir'] = DataProvider::getWorkingDir(); $this->printProperties($remote_terminal, $args);
$out['listen'] = ZMConfig::get('global', 'host') . ':' . ZMConfig::get('global', 'port');
if (!isset($this->swoole_server_config['worker_num'])) {
if ((ZMConfig::get('global', 'runtime')['swoole_server_mode'] ?? SWOOLE_PROCESS) === SWOOLE_PROCESS) {
$out['worker'] = swoole_cpu_num() . ' (auto)';
} else {
$out['single_proc_mode'] = 'true';
}
} else {
$out['worker'] = $this->swoole_server_config['worker_num'];
}
$out['environment'] = ($args['env'] ?? null) === null ? 'default' : $args['env'];
$out['log_level'] = Console::getLevel();
$out['version'] = Framework::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->swoole_server_config['task_worker_num'])) {
$out['task_worker'] = $this->swoole_server_config['task_worker_num'];
}
if ((ZMConfig::get('global', 'sql_config')['sql_host'] ?? '') !== '') {
$conf = ZMConfig::get('global', 'sql_config');
$out['mysql_pool'] = $conf['sql_database'] . '@' . $conf['sql_host'] . ':' . $conf['sql_port'];
}
if ((ZMConfig::get('global', 'mysql_config')['host'] ?? '') !== '') {
$conf = ZMConfig::get('global', 'mysql_config');
$out['mysql'] = $conf['dbname'] . '@' . $conf['host'] . ':' . $conf['port'];
}
if (ZMConfig::get('global', 'redis_config')['host'] !== '') {
$conf = ZMConfig::get('global', 'redis_config');
$out['redis_pool'] = $conf['host'] . ':' . $conf['port'];
}
if (ZMConfig::get('global', 'static_file_server')['status'] !== false) {
$out['static_file_server'] = 'enabled';
}
if (self::$argv['show-php-ver'] !== false) {
$out['php_version'] = PHP_VERSION;
$out['swoole_version'] = SWOOLE_VERSION;
}
if ($add_port) {
$conf = ZMConfig::get('global', 'remote_terminal');
$out['terminal'] = $conf['host'] . ':' . $conf['port'];
}
if (LOAD_MODE === 0) {
echo Console::setColor("* Framework started with source mode.\n", $args['log-theme'] === null ? 'yellow' : '');
}
// $this->mapOutput($out); // 汉化操作
$printer = new TablePrinter($out);
$printer->setValueColor('random')->printAll();
} }
// 预览模式则直接提出 // 预览模式则直接提出
@@ -233,26 +184,31 @@ class Framework
); );
// 监听远程终端 // 监听远程终端
if ($add_port) { if ($remote_terminal) {
$conf = ZMConfig::get('global', 'remote_terminal') ?? [ $conf = ZMConfig::get('global', 'remote_terminal') ?? [
'status' => true, 'status' => true,
'host' => '127.0.0.1', 'host' => '127.0.0.1',
'port' => 20002, 'port' => 20002,
'token' => '', 'token' => '',
]; ];
$welcome_msg = Console::setColor('Welcome! You can use `help` for usage.', 'green');
$welcome_msg = capture_output([logger('trm'), 'info'], ['欢迎使用炸毛远程终端!输入 `help` 查看帮助!']);
$motd = capture_output(function () {
$this->printMotd();
});
/** @var Port $port */ /** @var Port $port */
$port = self::$server->listen($conf['host'], $conf['port'], SWOOLE_SOCK_TCP); $port = self::$server->listen($conf['host'], $conf['port'], SWOOLE_SOCK_TCP);
$port->set([ $port->set([
'open_http_protocol' => false, 'open_http_protocol' => false,
]); ]);
$port->on('connect', function (\Swoole\Server $serv, $fd) use ($welcome_msg, $conf) { $port->on('connect', function (\Swoole\Server $serv, $fd) use ($welcome_msg, $conf, $motd) {
ManagerGM::pushConnect($fd, 'terminal'); ManagerGM::pushConnect($fd, 'terminal');
// 推送欢迎信息 // 推送欢迎信息
$serv->send($fd, file_get_contents(working_dir() . '/config/motd.txt')); $serv->send($fd, $motd);
// 要求输入令牌 // 要求输入令牌
if (!empty($conf['token'])) { if (!empty($conf['token'])) {
$serv->send($fd, 'Please input token: '); $serv->send($fd, '请输入令牌:');
} else { } else {
$serv->send($fd, $welcome_msg . "\n>>> "); $serv->send($fd, $welcome_msg . "\n>>> ");
} }
@@ -262,38 +218,36 @@ class Framework
ob_start(); ob_start();
try { try {
$arr = LightCacheInside::get('light_array', 'input_token') ?? []; $arr = LightCacheInside::get('light_array', 'input_token') ?? [];
if (empty($arr[$fd] ?? '')) { if (empty($arr[$fd] ?? '') && $conf['token'] !== '') {
if ($conf['token'] != '') { $token = trim($data);
$token = trim($data); if ($token === $conf['token']) {
if ($token === $conf['token']) { SpinLock::transaction('input_token', static function () use ($fd, $token) {
SpinLock::transaction('input_token', function () use ($fd, $token) { $arr = LightCacheInside::get('light_array', 'input_token');
$arr = LightCacheInside::get('light_array', 'input_token'); $arr[$fd] = $token;
$arr[$fd] = $token; LightCacheInside::set('light_array', 'input_token', $arr);
LightCacheInside::set('light_array', 'input_token', $arr); });
}); $serv->send($fd, capture_output([logger('trm'), 'info'], ['令牌验证成功!']));
$serv->send($fd, Console::setColor("Auth success!!\n", 'green')); $serv->send($fd, $welcome_msg . "\n>>> ");
$serv->send($fd, $welcome_msg . "\n>>> "); } else {
} else { $serv->send($fd, capture_output([logger('trm'), 'error'], ['令牌验证失败!']));
$serv->send($fd, Console::setColor("Auth failed!!\n", 'red')); $serv->close($fd);
$serv->close($fd);
}
return;
} }
return;
} }
if (trim($data) == 'exit' || trim($data) == 'q') { if (trim($data) === 'exit' || trim($data) === 'q') {
$serv->send($fd, Console::setColor("Bye!\n", 'blue')); $serv->send($fd, capture_output([logger('trm'), 'info'], ['再见!']));
$serv->close($fd); $serv->close($fd);
return; return;
} }
Terminal::executeCommand(trim($data)); Terminal::executeCommand(trim($data));
} catch (Exception $e) { } catch (Exception $e) {
$error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')'; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode('E00009') . 'Uncaught exception ' . get_class($e) . ' when calling "open": ' . $error_msg); logger('trm')->error(zm_internal_errcode('E00009') . 'Uncaught exception ' . get_class($e) . ' when calling "open": ' . $error_msg);
Console::trace(); logger('trm')->error($e->getTraceAsString());
} catch (Error $e) { } catch (Error $e) {
$error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')'; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode('E00009') . 'Uncaught ' . get_class($e) . ' when calling "open": ' . $error_msg); logger('trm')->error(zm_internal_errcode('E00009') . 'Uncaught ' . get_class($e) . ' when calling "open": ' . $error_msg);
Console::trace(); logger('trm')->error($e->getTraceAsString());
} }
$r = ob_get_clean(); $r = ob_get_clean();
@@ -307,7 +261,6 @@ class Framework
$port->on('close', function ($serv, $fd) { $port->on('close', function ($serv, $fd) {
ManagerGM::popConnect($fd); ManagerGM::popConnect($fd);
// echo "Client: Close.\n";
}); });
} }
@@ -317,7 +270,7 @@ class Framework
// 非静默模式下,打印欢迎信息 // 非静默模式下,打印欢迎信息
if (!self::$argv['private-mode']) { if (!self::$argv['private-mode']) {
self::printMotd(isset($printer) ? $printer->fetchTerminalSize() : 79); $this->printMotd();
} }
$global_hook = ZMConfig::get('global', 'runtime')['swoole_coroutine_hook_flags'] ?? (SWOOLE_HOOK_ALL & (~SWOOLE_HOOK_CURL)); $global_hook = ZMConfig::get('global', 'runtime')['swoole_coroutine_hook_flags'] ?? (SWOOLE_HOOK_ALL & (~SWOOLE_HOOK_CURL));
@@ -327,9 +280,6 @@ class Framework
Runtime::enableCoroutine(false, SWOOLE_HOOK_ALL); Runtime::enableCoroutine(false, SWOOLE_HOOK_ALL);
} }
global $asd;
$asd = get_included_files();
// 注册 Swoole Server 的事件 // 注册 Swoole Server 的事件
$this->registerServerEvents(); $this->registerServerEvents();
@@ -349,68 +299,36 @@ class Framework
// 注册全局错误处理器 // 注册全局错误处理器
set_error_handler(static function ($error_no, $error_msg, $error_file, $error_line) { set_error_handler(static function ($error_no, $error_msg, $error_file, $error_line) {
switch ($error_no) { $tips = [
case E_WARNING: E_WARNING => ['PHP Warning: ', 'warning'],
$level_tips = 'PHP Warning: '; E_NOTICE => ['PHP Notice: ', 'notice'],
break; E_USER_ERROR => ['PHP Error: ', 'error'],
case E_NOTICE: E_USER_WARNING => ['PHP Warning: ', 'warning'],
$level_tips = 'PHP Notice: '; E_USER_NOTICE => ['PHP Notice: ', 'notice'],
break; E_STRICT => ['PHP Strict: ', 'notice'],
case E_DEPRECATED: E_RECOVERABLE_ERROR => ['PHP Recoverable Error: ', 'error'],
$level_tips = 'PHP Deprecated: '; E_DEPRECATED => ['PHP Deprecated: ', 'notice'],
break; E_USER_DEPRECATED => ['PHP User Deprecated: ', 'notice'],
case E_USER_ERROR: ];
$level_tips = 'User Error: '; $level_tip = $tips[$error_no] ?? ['PHP Unknown: ', 'error'];
break; $error = $level_tip[0] . $error_msg . ' in ' . $error_file . ' on ' . $error_line;
case E_USER_WARNING: logger()->{$level_tip[1]}($error);
$level_tips = 'User Warning: ';
break;
case E_USER_NOTICE:
$level_tips = 'User Notice: ';
break;
case E_USER_DEPRECATED:
$level_tips = 'User Deprecated: ';
break;
case E_STRICT:
$level_tips = 'PHP Strict: ';
break;
default:
$level_tips = 'Unkonw Type Error: ';
break;
}
$error = $level_tips . $error_msg . ' in ' . $error_file . ' on ' . $error_line;
Console::warning($error);
// 如果 return false 则错误会继续递交给 PHP 标准错误处理 // 如果 return false 则错误会继续递交给 PHP 标准错误处理
return true; return true;
}, E_ALL | E_STRICT); }, E_ALL | E_STRICT);
} catch (Exception $e) { } catch (Exception $e) {
Console::error('框架初始化出现异常,请检查!'); logger()->emergency('框架初始化失败,请检查!');
Console::error(zm_internal_errcode('E00010') . $e->getMessage()); logger()->emergency(zm_internal_errcode('E00010') . $e->getMessage());
if (strpos($e->getMessage(), 'Address already in use') !== false) { if (strpos($e->getMessage(), 'Address already in use') !== false) {
if (!ProcessManager::isStateEmpty()) { if (!ProcessManager::isStateEmpty()) {
Console::error('检测到可能残留框架的工作进程请先通过命令杀死server:stop --force'); logger()->alert('检测到可能残留框架的工作进程请先通过命令杀死server:stop --force');
} }
} }
Console::debug($e); logger()->debug($e);
exit; exit;
} }
} }
public function start()
{
try {
self::$loaded_files = get_included_files();
LightCacheInside::set('tmp_kv', 'start_time', microtime(true));
self::$server->start();
zm_atomic('server_is_stopped')->set(1);
if (!self::$argv['private-mode']) {
Console::log('zhamao-framework is stopped.');
}
} catch (Throwable $e) {
exit(zm_internal_errcode('E00011') . 'Framework has an uncaught ' . get_class($e) . ': ' . $e->getMessage() . PHP_EOL);
}
}
public static function loadFrameworkState() public static function loadFrameworkState()
{ {
if (!file_exists(DataProvider::getDataFolder() . '.state.json')) { if (!file_exists(DataProvider::getDataFolder() . '.state.json')) {
@@ -428,26 +346,27 @@ class Framework
return file_put_contents(DataProvider::getDataFolder() . '.state.json', json_encode($data, 64 | 128 | 256)); return file_put_contents(DataProvider::getDataFolder() . '.state.json', json_encode($data, 64 | 128 | 256));
} }
public function mapOutput(array &$out) public function start()
{ {
$translate = [ try {
'working_dir' => '工作目录', self::$loaded_files = get_included_files();
'listen' => '监听地址', LightCacheInside::set('tmp_kv', 'start_time', microtime(true));
'worker' => '工作进程数', self::$server->start();
'environment' => '环境类型', zm_atomic('server_is_stopped')->set(1);
'log_level' => '日志级别', if (!self::$argv['private-mode']) {
'version' => '框架版本', logger()->info('炸毛框架已停止!');
'master_pid' => '主进程PID',
];
foreach ($out as $k => $v) {
if (isset($translate[$k])) {
$this->arrayChangeKey($out, $k, $translate[$k]);
} }
} catch (Throwable $e) {
exit(zm_internal_errcode('E00011') . '框架发生未捕获的异常:' . get_class($e) . ': ' . $e->getMessage() . PHP_EOL);
} }
} }
private static function printMotd($tty_width) /**
* 打印 MOTD
*/
private function printMotd(): void
{ {
$tty_width = (new TablePrinter([]))->fetchTerminalSize();
if (file_exists(DataProvider::getSourceRootDir() . '/config/motd.txt')) { if (file_exists(DataProvider::getSourceRootDir() . '/config/motd.txt')) {
$motd = file_get_contents(DataProvider::getSourceRootDir() . '/config/motd.txt'); $motd = file_get_contents(DataProvider::getSourceRootDir() . '/config/motd.txt');
} else { } else {
@@ -462,8 +381,34 @@ class Framework
} }
/** /**
* @noinspection PhpIncludeInspection * 翻译属性
*/ */
private function translateProperties(array &$properties): void
{
$translations = [
'working_dir' => '工作目录',
'listen' => '监听地址',
'worker' => '工作进程数',
'environment' => '环境类型',
'log_level' => '日志级别',
'version' => '框架版本',
'master_pid' => '主进程 PID',
'app_version' => '应用版本',
'task_worker' => '任务进程数',
'mysql_pool' => '数据库',
'mysql' => '数据库',
'redis_pool' => 'Redis',
'static_file_server' => '静态文件托管',
'php_version' => 'PHP 版本',
'swoole_version' => 'Swoole 版本',
];
foreach ($properties as $k => $v) {
if (isset($translations[$k])) {
$this->changeArrayKey($properties, $k, $translations[$k]);
}
}
}
private function loadServerEvents() private function loadServerEvents()
{ {
if (Phar::running() !== '') { if (Phar::running() !== '') {
@@ -475,12 +420,12 @@ class Framework
$r = exec(PHP_BINARY . ' ' . DataProvider::getFrameworkRootDir() . '/src/ZM/script_setup_loader.php', $output, $result_code); $r = exec(PHP_BINARY . ' ' . DataProvider::getFrameworkRootDir() . '/src/ZM/script_setup_loader.php', $output, $result_code);
} }
if ($result_code !== 0) { if ($result_code !== 0) {
Console::error('Parsing code error!'); logger()->emergency('代码解析错误!');
exit(1); exit(1);
} }
$json = json_decode($r, true); $json = json_decode($r, true);
if (!is_array($json)) { if (!is_array($json)) {
Console::warning(zm_internal_errcode('E00012') . 'Parsing @SwooleHandler and @OnSetup error!'); logger()->error(zm_internal_errcode('E00012') . '解析 @SwooleHandler @OnSetup 时发生错误,请检查代码!');
} }
$this->setup_events = $json; $this->setup_events = $json;
} }
@@ -509,7 +454,7 @@ class Framework
} }
foreach (($this->setup_events['setup'] ?? []) as $v) { foreach (($this->setup_events['setup'] ?? []) as $v) {
Console::debug('Calling @OnSetup: ' . $v['class']); logger()->debug('Calling @OnSetup: ' . $v['class']);
$c = ZMUtil::getModInstance($v['class']); $c = ZMUtil::getModInstance($v['class']);
$method = $v['method']; $method = $v['method'];
$c->{$method}(); $c->{$method}();
@@ -523,104 +468,175 @@ class Framework
} }
/** /**
* 解析命令行的 $argv 参数 * 解析命令行的 $argv 参数
* *
* @param array $args 命令行参数 * @param array $args 命令行参数
* @param bool|string $add_port 是否添加端口号 * @throws InvalidArgumentException 参数不正确,框架需要捕获并终止启动
* @throws ConfigException * @return array 解析后并需要处理的参数
*/ */
private function parseCliArgs(array $args, &$add_port) private function parseCliArgs(array $args, array $defaults): array
{ {
$coroutine_mode = true; $coroutine_mode = true;
global $terminal_id; global $terminal_id;
$terminal_id = uuidgen(); $terminal_id = uuidgen();
$error_occur = false;
$remote_terminal = $defaults['remote_terminal'];
foreach ($args as $x => $y) { foreach ($args as $x => $y) {
if ($y) { if ($y === false || is_null($y)) {
switch ($x) { continue;
case 'worker-num': }
if (intval($y) >= 1 && intval($y) <= 1024) { switch ($x) {
$this->swoole_server_config['worker_num'] = intval($y); case 'worker-num':
} else { if ((int) $y >= 1 && (int) $y <= 1024) {
Console::warning(zm_internal_errcode('E00013') . 'Invalid worker num! Turn to default value (' . ($this->swoole_server_config['worker_num'] ?? swoole_cpu_num()) . ')'); $this->swoole_server_config['worker_num'] = (int) $y;
} } else {
break; logger()->emergency(zm_internal_errcode('E00013') . '传入的 worker_num 参数不合法!必须在 1-1024 之间!');
case 'task-worker-num': $error_occur = true;
if (intval($y) >= 1 && intval($y) <= 1024) { }
$this->swoole_server_config['task_worker_num'] = intval($y); break;
$this->swoole_server_config['task_enable_coroutine'] = true; case 'task-worker-num':
} else { if ((int) $y >= 1 && (int) $y <= 1024) {
Console::warning(zm_internal_errcode('E00013') . 'Invalid worker num! Turn to default value (0)'); $this->swoole_server_config['task_worker_num'] = (int) $y;
} $this->swoole_server_config['task_enable_coroutine'] = true;
break; } else {
case 'disable-coroutine': logger()->emergency(zm_internal_errcode('E00013') . '传入的 task_worker_num 参数不合法!必须在 1-1024 之间!');
$coroutine_mode = false; $error_occur = true;
break; }
case 'debug-mode': break;
self::$argv['disable-safe-exit'] = true; case 'disable-coroutine':
$coroutine_mode = false; $coroutine_mode = false;
$terminal_id = null; break;
self::$argv['watch'] = true; case 'debug-mode':
echo "* You are in debug mode, do not use in production!\n"; self::$argv['disable-safe-exit'] = true;
break; $coroutine_mode = false;
case 'daemon': $terminal_id = null;
$this->swoole_server_config['daemonize'] = 1; self::$argv['watch'] = true;
Console::$theme = 'no-color'; logger()->notice('已进入调试模式,请勿在生产环境中使用!');
Console::log('已启用守护进程,输出重定向到 ' . $this->swoole_server_config['log_file']); break;
$terminal_id = null; case 'daemon':
break; $this->swoole_server_config['daemonize'] = 1;
case 'disable-console-input': Console::$theme = 'no-color';
case 'no-interaction': Console::log('已启用守护进程,输出重定向到 ' . $this->swoole_server_config['log_file']);
$terminal_id = null; $terminal_id = null;
break; break;
case 'log-error': case 'disable-console-input':
Console::setLevel(0); case 'no-interaction':
break; $terminal_id = null;
case 'log-warning': break;
Console::setLevel(1); case 'log-error':
break; Console::setLevel(0);
case 'log-info': break;
Console::setLevel(2); case 'log-warning':
break; Console::setLevel(1);
case 'log-verbose': break;
case 'verbose': case 'log-info':
Console::setLevel(3); Console::setLevel(2);
break; break;
case 'log-debug': case 'log-verbose':
Console::setLevel(4); case 'verbose':
break; Console::setLevel(3);
case 'audit-mode': break;
Console::warning('审计模式已开启请正常执行需要审计的流程然后Ctrl+C正常结束框架'); case 'log-debug':
Console::warning('审计的日志文件将存放到:' . DataProvider::getWorkingDir() . '/audit.log'); Console::setLevel(4);
if (file_exists(DataProvider::getWorkingDir() . '/audit.log')) { break;
unlink(DataProvider::getWorkingDir() . '/audit.log'); case 'audit-mode':
} logger()->notice('审计模式已开启请正常执行需要审计的流程然后Ctrl+C正常结束框架');
Console::info('框架将于5秒后开始启动...'); logger()->notice('审计的日志文件将存放到:' . DataProvider::getWorkingDir() . '/audit.log');
Console::setOutputFile(DataProvider::getWorkingDir() . '/audit.log'); if (file_exists(DataProvider::getWorkingDir() . '/audit.log')) {
Console::setLevel(4); unlink(DataProvider::getWorkingDir() . '/audit.log');
sleep(5); }
break; logger()->notice('框架将于5秒后开始启动...');
case 'log-theme': Console::setOutputFile(DataProvider::getWorkingDir() . '/audit.log');
Console::$theme = $y; Console::setLevel(4);
break; sleep(5);
case 'remote-terminal': break;
$add_port = true; case 'log-theme':
break; Console::$theme = $y;
case 'show-php-ver': break;
default: case 'remote-terminal':
// Console::info("Calculating ".$x); $remote_terminal = true;
// dump($y); break;
break; case 'show-php-ver':
} default:
break;
} }
} }
return $coroutine_mode; if ($error_occur) {
throw new InvalidArgumentException('命令行参数解析错误,请参阅上方日志!');
}
return [$coroutine_mode, $terminal_id, $remote_terminal];
} }
private function arrayChangeKey(array &$arr, $old_key, $new_key) /**
* 更换数组键名
*
* @param mixed $old_key
* @param mixed $new_key
*/
private function changeArrayKey(array &$arr, $old_key, $new_key): void
{ {
$keys = array_keys($arr); $keys = array_keys($arr);
$values = array_values($arr); $keys[array_search($old_key, $keys, false)] = $new_key;
$keys[array_search($old_key, $keys)] = $new_key; $arr = ($t = array_combine($keys, $arr)) ? $t : $arr;
$arr = array_combine($keys, $values); }
/**
* 打印属性表格
*/
private function printProperties(bool $remote_terminal, array $args): void
{
$properties = [];
$properties['working_dir'] = DataProvider::getWorkingDir();
$properties['listen'] = ZMConfig::get('global', 'host') . ':' . ZMConfig::get('global', 'port');
if (!isset($this->swoole_server_config['worker_num'])) {
if ((ZMConfig::get('global', 'runtime')['swoole_server_mode'] ?? SWOOLE_PROCESS) === SWOOLE_PROCESS) {
$properties['worker'] = swoole_cpu_num() . ' (auto)';
} else {
$properties['single_proc_mode'] = 'true';
}
} else {
$properties['worker'] = $this->swoole_server_config['worker_num'];
}
$properties['environment'] = ($args['env'] ?? null) === null ? 'default' : $args['env'];
$properties['log_level'] = strtoupper(zm_config('logging.level'));
$properties['version'] = self::VERSION . (LOAD_MODE === 0 ? (' (build ' . ZM_VERSION_ID . ')') : '');
$properties['master_pid'] = posix_getpid();
if (APP_VERSION !== 'unknown') {
$properties['app_version'] = APP_VERSION;
}
if (isset($this->swoole_server_config['task_worker_num'])) {
$properties['task_worker'] = $this->swoole_server_config['task_worker_num'];
}
if ((ZMConfig::get('global', 'sql_config')['sql_host'] ?? '') !== '') {
$conf = ZMConfig::get('global', 'sql_config');
$properties['mysql_pool'] = $conf['sql_database'] . '@' . $conf['sql_host'] . ':' . $conf['sql_port'];
}
if ((ZMConfig::get('global', 'mysql_config')['host'] ?? '') !== '') {
$conf = ZMConfig::get('global', 'mysql_config');
$properties['mysql'] = $conf['dbname'] . '@' . $conf['host'] . ':' . $conf['port'];
}
if (ZMConfig::get('global', 'redis_config')['host'] !== '') {
$conf = ZMConfig::get('global', 'redis_config');
$properties['redis_pool'] = $conf['host'] . ':' . $conf['port'];
}
if (ZMConfig::get('global', 'static_file_server')['status'] !== false) {
$properties['static_file_server'] = 'enabled';
}
if (self::$argv['show-php-ver'] !== false) {
$properties['php_version'] = PHP_VERSION;
$properties['swoole_version'] = SWOOLE_VERSION;
}
if ($remote_terminal) {
$conf = ZMConfig::get('global', 'remote_terminal');
$properties['terminal'] = $conf['host'] . ':' . $conf['port'];
}
if (LOAD_MODE === 0) {
logger()->info('框架正以源码模式启动');
}
$this->translateProperties($properties);
$printer = new TablePrinter($properties);
$printer->setValueColor('random')->printAll();
} }
} }

View File

@@ -788,7 +788,20 @@ function is_assoc_array(array $array): bool
/** /**
* 返回 Logger 实例 * 返回 Logger 实例
*/ */
function logger(): LoggerInterface function logger(...$args): LoggerInterface
{ {
if (!app()->has(LoggerInterface::class)) {
return zm_config('logging.logger')(...$args);
}
return resolve(LoggerInterface::class); return resolve(LoggerInterface::class);
} }
/**
* 捕获输出
*/
function capture_output(callable $callback, array $args = []): string
{
ob_start();
$callback(...$args);
return ob_get_clean();
}