2020-08-31 10:11:06 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
2022-03-15 18:05:33 +08:00
|
|
|
|
declare(strict_types=1);
|
2020-08-31 10:11:06 +08:00
|
|
|
|
|
|
|
|
|
|
namespace ZM;
|
|
|
|
|
|
|
|
|
|
|
|
use Doctrine\Common\Annotations\AnnotationReader;
|
2021-03-24 23:34:46 +08:00
|
|
|
|
use Error;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use Exception;
|
2021-07-09 01:38:30 +08:00
|
|
|
|
use Phar;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
use ReflectionClass;
|
|
|
|
|
|
use ReflectionException;
|
|
|
|
|
|
use Swoole\Runtime;
|
2021-03-24 23:34:46 +08:00
|
|
|
|
use Swoole\Server\Port;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
use Swoole\WebSocket\Server;
|
2021-06-16 00:17:30 +08:00
|
|
|
|
use Throwable;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
use ZM\Annotation\Swoole\SwooleHandler;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Config\ZMConfig;
|
|
|
|
|
|
use ZM\ConnectionManager\ManagerGM;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
use ZM\Console\Console;
|
2021-03-02 21:24:31 +08:00
|
|
|
|
use ZM\Console\TermColor;
|
2022-03-13 22:46:22 +08:00
|
|
|
|
use ZM\Exception\ZMKnownException;
|
2020-09-29 15:07:43 +08:00
|
|
|
|
use ZM\Store\LightCache;
|
2020-11-03 21:02:24 +08:00
|
|
|
|
use ZM\Store\LightCacheInside;
|
|
|
|
|
|
use ZM\Store\Lock\SpinLock;
|
|
|
|
|
|
use ZM\Store\ZMAtomic;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Utils\DataProvider;
|
2021-03-24 23:34:46 +08:00
|
|
|
|
use ZM\Utils\Terminal;
|
2020-09-29 15:07:43 +08:00
|
|
|
|
use ZM\Utils\ZMUtil;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
use function date_default_timezone_set;
|
|
|
|
|
|
use function define;
|
2021-09-01 14:14:00 +08:00
|
|
|
|
use function exec;
|
|
|
|
|
|
use function explode;
|
|
|
|
|
|
use function file_exists;
|
|
|
|
|
|
use function file_get_contents;
|
|
|
|
|
|
use function file_put_contents;
|
|
|
|
|
|
use function get_class;
|
|
|
|
|
|
use function get_included_files;
|
|
|
|
|
|
use function in_array;
|
|
|
|
|
|
use function intval;
|
|
|
|
|
|
use function is_array;
|
|
|
|
|
|
use function is_dir;
|
|
|
|
|
|
use function json_decode;
|
|
|
|
|
|
use function json_encode;
|
|
|
|
|
|
use function mkdir;
|
|
|
|
|
|
use function ob_get_clean;
|
|
|
|
|
|
use function ob_start;
|
|
|
|
|
|
use function posix_getpid;
|
|
|
|
|
|
use function str_pad;
|
|
|
|
|
|
use function strlen;
|
|
|
|
|
|
use function substr;
|
|
|
|
|
|
use function swoole_cpu_num;
|
|
|
|
|
|
use function trim;
|
|
|
|
|
|
use function uuidgen;
|
|
|
|
|
|
use function working_dir;
|
|
|
|
|
|
use function zm_atomic;
|
|
|
|
|
|
use function zm_internal_errcode;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
|
|
|
|
|
|
class Framework
|
|
|
|
|
|
{
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @var array
|
|
|
|
|
|
*/
|
2020-09-29 15:07:43 +08:00
|
|
|
|
public static $argv;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
|
2020-08-31 10:11:06 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @var Server
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static $server;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
|
2021-03-24 23:34:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @var string[]
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static $loaded_files = [];
|
2022-03-15 18:05:33 +08:00
|
|
|
|
|
|
|
|
|
|
public static $instant_mode = false;
|
|
|
|
|
|
|
2020-08-31 10:11:06 +08:00
|
|
|
|
/**
|
2022-03-15 18:05:33 +08:00
|
|
|
|
* @var null|array|bool|mixed
|
2020-08-31 10:11:06 +08:00
|
|
|
|
*/
|
|
|
|
|
|
private $server_set;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
|
2021-06-16 00:17:30 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @var array
|
|
|
|
|
|
*/
|
|
|
|
|
|
private $setup_events = [];
|
2020-08-31 10:11:06 +08:00
|
|
|
|
|
2022-03-13 22:46:22 +08:00
|
|
|
|
public function __construct($args = [], $instant_mode = false)
|
|
|
|
|
|
{
|
2021-11-02 16:01:24 +08:00
|
|
|
|
$tty_width = $this->getTtyWidth();
|
|
|
|
|
|
self::$instant_mode = $instant_mode;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
self::$argv = $args;
|
2021-06-16 00:17:30 +08:00
|
|
|
|
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
|
2022-03-15 18:05:33 +08:00
|
|
|
|
ZMConfig::setEnv($args['env'] ?? '');
|
|
|
|
|
|
if (ZMConfig::get('global') === false) {
|
|
|
|
|
|
echo zm_internal_errcode('E00007') . 'Global config load failed: ' . ZMConfig::$last_error . "\nError path: " . DataProvider::getSourceRootDir() . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n";
|
|
|
|
|
|
exit(1);
|
2020-12-20 18:49:03 +08:00
|
|
|
|
}
|
2021-03-16 01:34:17 +08:00
|
|
|
|
|
2022-03-20 16:23:07 +08:00
|
|
|
|
// 定义常量
|
2022-03-15 18:05:33 +08:00
|
|
|
|
include_once 'global_defines.php';
|
2021-03-16 01:34:17 +08:00
|
|
|
|
|
2020-09-29 15:07:43 +08:00
|
|
|
|
try {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$sw = ZMConfig::get('global');
|
|
|
|
|
|
if (!is_dir($sw['zm_data'])) {
|
|
|
|
|
|
mkdir($sw['zm_data']);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!is_dir($sw['config_dir'])) {
|
|
|
|
|
|
mkdir($sw['config_dir']);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!is_dir($sw['crash_dir'])) {
|
|
|
|
|
|
mkdir($sw['crash_dir']);
|
|
|
|
|
|
}
|
|
|
|
|
|
ManagerGM::init(ZMConfig::get('global', 'swoole')['max_connection'] ?? 2048, 0.5, [
|
2020-09-29 15:07:43 +08:00
|
|
|
|
[
|
2022-03-15 18:05:33 +08:00
|
|
|
|
'key' => 'connect_id',
|
|
|
|
|
|
'type' => 'string',
|
|
|
|
|
|
'size' => 30,
|
2020-09-29 15:07:43 +08:00
|
|
|
|
],
|
|
|
|
|
|
[
|
2022-03-15 18:05:33 +08:00
|
|
|
|
'key' => 'type',
|
|
|
|
|
|
'type' => 'int',
|
|
|
|
|
|
],
|
2020-09-29 15:07:43 +08:00
|
|
|
|
]);
|
|
|
|
|
|
} catch (ConnectionManager\TableException $e) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
echo zm_internal_errcode('E00008') . $e->getMessage() . PHP_EOL;
|
|
|
|
|
|
exit(1);
|
2020-09-29 15:07:43 +08:00
|
|
|
|
}
|
2020-08-31 10:11:06 +08:00
|
|
|
|
try {
|
|
|
|
|
|
Console::init(
|
2022-03-15 18:05:33 +08:00
|
|
|
|
ZMConfig::get('global', 'info_level') ?? 2,
|
2020-08-31 10:11:06 +08:00
|
|
|
|
self::$server,
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$args['log-theme'] ?? 'default',
|
|
|
|
|
|
($o = ZMConfig::get('console_color')) === false ? [] : $o
|
2020-08-31 10:11:06 +08:00
|
|
|
|
);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if ((ZMConfig::get('global', 'runtime')['save_console_log_file'] ?? false) !== false) {
|
|
|
|
|
|
Console::setOutputFile(ZMConfig::get('global', 'runtime')['save_console_log_file']);
|
2022-01-08 16:19:43 +08:00
|
|
|
|
}
|
2020-08-31 10:11:06 +08:00
|
|
|
|
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$timezone = ZMConfig::get('global', 'timezone') ?? 'Asia/Shanghai';
|
2020-08-31 10:11:06 +08:00
|
|
|
|
date_default_timezone_set($timezone);
|
|
|
|
|
|
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$this->server_set = ZMConfig::get('global', 'swoole');
|
|
|
|
|
|
$this->server_set['log_level'] = SWOOLE_LOG_DEBUG;
|
|
|
|
|
|
$add_port = ZMConfig::get('global', 'remote_terminal')['status'] ?? false;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
|
2022-03-20 16:23:07 +08:00
|
|
|
|
// if ($instant_mode) {
|
2022-03-13 22:46:22 +08:00
|
|
|
|
$this->loadServerEvents();
|
2022-03-20 16:23:07 +08:00
|
|
|
|
// }
|
2021-06-16 00:17:30 +08:00
|
|
|
|
|
2021-03-24 23:34:46 +08:00
|
|
|
|
$this->parseCliArgs(self::$argv, $add_port);
|
2021-06-16 00:17:30 +08:00
|
|
|
|
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!isset($this->server_set['max_wait_time'])) {
|
|
|
|
|
|
$this->server_set['max_wait_time'] = 5;
|
2021-03-29 15:34:24 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$worker = $this->server_set['worker_num'] ?? swoole_cpu_num();
|
|
|
|
|
|
define('ZM_WORKER_NUM', $worker);
|
2021-06-16 00:17:30 +08:00
|
|
|
|
|
2021-03-24 23:34:46 +08:00
|
|
|
|
ZMAtomic::init();
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$out['working_dir'] = DataProvider::getWorkingDir();
|
2021-06-16 00:17:30 +08:00
|
|
|
|
|
2021-03-02 21:24:31 +08:00
|
|
|
|
// 打印初始信息
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$out['listen'] = ZMConfig::get('global', 'host') . ':' . ZMConfig::get('global', 'port');
|
|
|
|
|
|
if (!isset($this->server_set['worker_num'])) {
|
|
|
|
|
|
if ((ZMConfig::get('global', 'runtime')['swoole_server_mode'] ?? SWOOLE_PROCESS) == SWOOLE_PROCESS) {
|
|
|
|
|
|
$out['worker'] = swoole_cpu_num() . ' (auto)';
|
2021-07-09 01:38:30 +08:00
|
|
|
|
} else {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$out['single_proc_mode'] = 'true';
|
2021-07-09 01:38:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$out['worker'] = $this->server_set['worker_num'];
|
|
|
|
|
|
}
|
|
|
|
|
|
$out['environment'] = ($args['env'] ?? null) === 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;
|
2021-07-09 01:38:30 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (isset($this->server_set['task_worker_num'])) {
|
|
|
|
|
|
$out['task_worker'] = $this->server_set['task_worker_num'];
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
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'];
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if ((ZMConfig::get('global', 'mysql_config')['host'] ?? '') !== '') {
|
|
|
|
|
|
$conf = ZMConfig::get('global', 'mysql_config');
|
|
|
|
|
|
$out['mysql'] = $conf['dbname'] . '@' . $conf['host'] . ':' . $conf['port'];
|
2021-07-09 01:38:30 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (ZMConfig::get('global', 'redis_config')['host'] !== '') {
|
|
|
|
|
|
$conf = ZMConfig::get('global', 'redis_config');
|
|
|
|
|
|
$out['redis_pool'] = $conf['host'] . ':' . $conf['port'];
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (ZMConfig::get('global', 'static_file_server')['status'] !== false) {
|
|
|
|
|
|
$out['static_file_server'] = 'enabled';
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (self::$argv['show-php-ver'] !== false) {
|
|
|
|
|
|
$out['php_version'] = PHP_VERSION;
|
|
|
|
|
|
$out['swoole_version'] = SWOOLE_VERSION;
|
2021-03-08 00:48:51 +08:00
|
|
|
|
}
|
2021-07-04 15:45:30 +08:00
|
|
|
|
|
2021-03-24 23:34:46 +08:00
|
|
|
|
if ($add_port) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$conf = ZMConfig::get('global', 'remote_terminal');
|
|
|
|
|
|
$out['terminal'] = $conf['host'] . ':' . $conf['port'];
|
2021-03-24 23:34:46 +08:00
|
|
|
|
}
|
2021-03-02 21:24:31 +08:00
|
|
|
|
|
2022-03-15 18:05:33 +08:00
|
|
|
|
self::printProps($out, $tty_width, $args['log-theme'] === null);
|
|
|
|
|
|
if ($args['preview'] ?? false) {
|
2021-05-08 10:02:41 +08:00
|
|
|
|
exit();
|
|
|
|
|
|
}
|
2021-06-16 00:17:30 +08:00
|
|
|
|
|
2021-07-09 01:38:30 +08:00
|
|
|
|
self::$server = new Server(
|
2022-03-15 18:05:33 +08:00
|
|
|
|
ZMConfig::get('global', 'host'),
|
|
|
|
|
|
ZMConfig::get('global', 'port'),
|
|
|
|
|
|
ZMConfig::get('global', 'runtime')['swoole_server_mode'] ?? SWOOLE_PROCESS
|
2021-07-09 01:38:30 +08:00
|
|
|
|
);
|
2021-03-06 17:22:42 +08:00
|
|
|
|
|
2021-03-24 23:34:46 +08:00
|
|
|
|
if ($add_port) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$conf = ZMConfig::get('global', 'remote_terminal') ?? [
|
|
|
|
|
|
'status' => true,
|
|
|
|
|
|
'host' => '127.0.0.1',
|
|
|
|
|
|
'port' => 20002,
|
|
|
|
|
|
'token' => '',
|
|
|
|
|
|
];
|
|
|
|
|
|
$welcome_msg = Console::setColor('Welcome! You can use `help` for usage.', 'green');
|
2021-03-24 23:34:46 +08:00
|
|
|
|
/** @var Port $port */
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$port = self::$server->listen($conf['host'], $conf['port'], SWOOLE_SOCK_TCP);
|
2021-03-24 23:34:46 +08:00
|
|
|
|
$port->set([
|
2022-03-15 18:05:33 +08:00
|
|
|
|
'open_http_protocol' => false,
|
2021-03-24 23:34:46 +08:00
|
|
|
|
]);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$port->on('connect', function (?\Swoole\Server $serv, $fd) use ($welcome_msg, $conf) {
|
|
|
|
|
|
ManagerGM::pushConnect($fd, 'terminal');
|
|
|
|
|
|
$serv->send($fd, file_get_contents(working_dir() . '/config/motd.txt'));
|
|
|
|
|
|
if (!empty($conf['token'])) {
|
|
|
|
|
|
$serv->send($fd, 'Please input token: ');
|
2021-03-24 23:34:46 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
$serv->send($fd, $welcome_msg . "\n>>> ");
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$port->on('receive', function ($serv, $fd, $reactor_id, $data) use ($welcome_msg, $conf) {
|
|
|
|
|
|
ob_start();
|
|
|
|
|
|
try {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$arr = LightCacheInside::get('light_array', 'input_token') ?? [];
|
2021-03-24 23:34:46 +08:00
|
|
|
|
if (empty($arr[$fd] ?? '')) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if ($conf['token'] != '') {
|
2021-03-24 23:34:46 +08:00
|
|
|
|
$token = trim($data);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if ($token === $conf['token']) {
|
|
|
|
|
|
SpinLock::transaction('input_token', function () use ($fd, $token) {
|
|
|
|
|
|
$arr = LightCacheInside::get('light_array', 'input_token');
|
2021-03-24 23:34:46 +08:00
|
|
|
|
$arr[$fd] = $token;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
LightCacheInside::set('light_array', 'input_token', $arr);
|
2021-03-24 23:34:46 +08:00
|
|
|
|
});
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$serv->send($fd, Console::setColor("Auth success!!\n", 'green'));
|
2021-03-24 23:34:46 +08:00
|
|
|
|
$serv->send($fd, $welcome_msg . "\n>>> ");
|
|
|
|
|
|
} else {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$serv->send($fd, Console::setColor("Auth failed!!\n", 'red'));
|
2021-03-24 23:34:46 +08:00
|
|
|
|
$serv->close($fd);
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (trim($data) == 'exit' || trim($data) == 'q') {
|
|
|
|
|
|
$serv->send($fd, Console::setColor("Bye!\n", 'blue'));
|
2021-03-24 23:34:46 +08:00
|
|
|
|
$serv->close($fd);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
Terminal::executeCommand(trim($data));
|
|
|
|
|
|
} catch (Exception $e) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$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);
|
2021-03-24 23:34:46 +08:00
|
|
|
|
Console::trace();
|
|
|
|
|
|
} catch (Error $e) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
|
|
|
|
|
|
Console::error(zm_internal_errcode('E00009') . 'Uncaught ' . get_class($e) . ' when calling "open": ' . $error_msg);
|
2021-03-24 23:34:46 +08:00
|
|
|
|
Console::trace();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$r = ob_get_clean();
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!empty($r)) {
|
|
|
|
|
|
$serv->send($fd, $r);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!in_array(trim($data), ['r', 'reload'])) {
|
|
|
|
|
|
$serv->send($fd, '>>> ');
|
|
|
|
|
|
}
|
2021-03-24 23:34:46 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$port->on('close', function ($serv, $fd) {
|
|
|
|
|
|
ManagerGM::popConnect($fd);
|
2022-03-20 16:23:07 +08:00
|
|
|
|
// echo "Client: Close.\n";
|
2021-03-24 23:34:46 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-03-06 17:22:42 +08:00
|
|
|
|
self::$server->set($this->server_set);
|
2021-03-13 15:16:10 +08:00
|
|
|
|
Console::setServer(self::$server);
|
2021-03-02 21:24:31 +08:00
|
|
|
|
self::printMotd($tty_width);
|
|
|
|
|
|
|
2020-08-31 10:11:06 +08:00
|
|
|
|
global $asd;
|
|
|
|
|
|
$asd = get_included_files();
|
2020-09-29 15:07:43 +08:00
|
|
|
|
// 注册 Swoole Server 的事件
|
|
|
|
|
|
$this->registerServerEvents();
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$r = ZMConfig::get('global', 'light_cache') ?? [
|
2022-03-20 16:23:07 +08:00
|
|
|
|
'size' => 512, // 最多允许储存的条数(需要2的倍数)
|
|
|
|
|
|
'max_strlen' => 32768, // 单行字符串最大长度(需要2的倍数)
|
|
|
|
|
|
'hash_conflict_proportion' => 0.6, // Hash冲突率(越大越好,但是需要的内存更多)
|
2022-03-15 18:05:33 +08:00
|
|
|
|
'persistence_path' => DataProvider::getDataFolder() . '_cache.json',
|
|
|
|
|
|
'auto_save_interval' => 900,
|
|
|
|
|
|
];
|
2020-11-03 21:02:24 +08:00
|
|
|
|
LightCache::init($r);
|
|
|
|
|
|
LightCacheInside::init();
|
2022-03-15 18:05:33 +08:00
|
|
|
|
SpinLock::init($r['size']);
|
2021-01-03 18:16:35 +08:00
|
|
|
|
set_error_handler(function ($error_no, $error_msg, $error_file, $error_line) {
|
|
|
|
|
|
switch ($error_no) {
|
|
|
|
|
|
case E_WARNING:
|
|
|
|
|
|
$level_tips = 'PHP Warning: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case E_NOTICE:
|
|
|
|
|
|
$level_tips = 'PHP Notice: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case E_DEPRECATED:
|
|
|
|
|
|
$level_tips = 'PHP Deprecated: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case E_USER_ERROR:
|
|
|
|
|
|
$level_tips = 'User Error: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case E_USER_WARNING:
|
|
|
|
|
|
$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;
|
|
|
|
|
|
} // do some handle
|
|
|
|
|
|
$error = $level_tips . $error_msg . ' in ' . $error_file . ' on ' . $error_line;
|
|
|
|
|
|
Console::warning($error); // 如果 return false 则错误会继续递交给 PHP 标准错误处理 /
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}, E_ALL | E_STRICT);
|
2020-08-31 10:11:06 +08:00
|
|
|
|
} catch (Exception $e) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
Console::error('Framework初始化出现错误,请检查!');
|
|
|
|
|
|
Console::error(zm_internal_errcode('E00010') . $e->getMessage());
|
2021-03-06 17:22:42 +08:00
|
|
|
|
Console::debug($e);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
exit;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-13 22:46:22 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 将各进程的pid写入文件,以备后续崩溃及僵尸进程处理使用
|
|
|
|
|
|
* @param int|string $pid
|
|
|
|
|
|
* @internal
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function saveProcessState(int $type, $pid, array $data = [])
|
|
|
|
|
|
{
|
|
|
|
|
|
switch ($type) {
|
|
|
|
|
|
case ZM_PROCESS_MASTER:
|
|
|
|
|
|
$file = _zm_pid_dir() . '/master.json';
|
|
|
|
|
|
$json = [
|
|
|
|
|
|
'pid' => intval($pid),
|
|
|
|
|
|
'stdout' => $data['stdout'],
|
2022-03-15 18:05:33 +08:00
|
|
|
|
'daemon' => $data['daemon'],
|
2022-03-13 22:46:22 +08:00
|
|
|
|
];
|
|
|
|
|
|
file_put_contents($file, json_encode($json, JSON_UNESCAPED_UNICODE));
|
|
|
|
|
|
return;
|
|
|
|
|
|
case ZM_PROCESS_MANAGER:
|
|
|
|
|
|
$file = _zm_pid_dir() . '/manager.pid';
|
|
|
|
|
|
file_put_contents($file, strval($pid));
|
|
|
|
|
|
return;
|
|
|
|
|
|
case ZM_PROCESS_WORKER:
|
|
|
|
|
|
$file = _zm_pid_dir() . '/worker.' . $data['worker_id'] . '.pid';
|
|
|
|
|
|
file_put_contents($file, strval($pid));
|
|
|
|
|
|
return;
|
|
|
|
|
|
case ZM_PROCESS_USER:
|
|
|
|
|
|
$file = _zm_pid_dir() . '/user.' . $data['process_name'] . '.pid';
|
|
|
|
|
|
file_put_contents($file, strval($pid));
|
|
|
|
|
|
return;
|
|
|
|
|
|
case ZM_PROCESS_TASKWORKER:
|
|
|
|
|
|
$file = _zm_pid_dir() . '/taskworker.' . $data['worker_id'] . '.pid';
|
|
|
|
|
|
file_put_contents($file, strval($pid));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 用于框架内部获取多进程运行状态的函数
|
2022-03-15 18:05:33 +08:00
|
|
|
|
* @param mixed $id_or_name
|
2022-03-13 22:46:22 +08:00
|
|
|
|
* @throws ZMKnownException
|
2022-03-15 18:05:33 +08:00
|
|
|
|
* @return false|int|mixed
|
2022-03-13 22:46:22 +08:00
|
|
|
|
* @internal
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function getProcessState(int $type, $id_or_name = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
$file = _zm_pid_dir();
|
|
|
|
|
|
switch ($type) {
|
|
|
|
|
|
case ZM_PROCESS_MASTER:
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!file_exists($file . '/master.json')) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
$json = json_decode(file_get_contents($file . '/master.json'), true);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if ($json !== null) {
|
|
|
|
|
|
return $json;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
2022-03-13 22:46:22 +08:00
|
|
|
|
case ZM_PROCESS_MANAGER:
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!file_exists($file . '/manager.pid')) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
return intval(file_get_contents($file . '/manager.pid'));
|
|
|
|
|
|
case ZM_PROCESS_WORKER:
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!is_int($id_or_name)) {
|
|
|
|
|
|
throw new ZMKnownException('E99999', 'worker_id必须为整数');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!file_exists($file . '/worker.' . $id_or_name . '.pid')) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
return intval(file_get_contents($file . '/worker.' . $id_or_name . '.pid'));
|
|
|
|
|
|
case ZM_PROCESS_USER:
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!is_string($id_or_name)) {
|
|
|
|
|
|
throw new ZMKnownException('E99999', 'process_name必须为字符串');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!file_exists($file . '/user.' . $id_or_name . '.pid')) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
return intval(file_get_contents($file . '/user.' . $id_or_name . '.pid'));
|
|
|
|
|
|
case ZM_PROCESS_TASKWORKER:
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!is_int($id_or_name)) {
|
|
|
|
|
|
throw new ZMKnownException('E99999', 'worker_id必须为整数');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!file_exists($file . '/taskworker.' . $id_or_name . '.pid')) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
return intval(file_get_contents($file . '/taskworker.' . $id_or_name . '.pid'));
|
|
|
|
|
|
default:
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2022-03-15 18:05:33 +08:00
|
|
|
|
* @param null $id_or_name
|
2022-03-13 22:46:22 +08:00
|
|
|
|
* @throws ZMKnownException
|
|
|
|
|
|
* @internal
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function removeProcessState(int $type, $id_or_name = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch ($type) {
|
|
|
|
|
|
case ZM_PROCESS_MASTER:
|
|
|
|
|
|
$file = _zm_pid_dir() . '/master.json';
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (file_exists($file)) {
|
|
|
|
|
|
unlink($file);
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
return;
|
|
|
|
|
|
case ZM_PROCESS_MANAGER:
|
|
|
|
|
|
$file = _zm_pid_dir() . '/manager.pid';
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (file_exists($file)) {
|
|
|
|
|
|
unlink($file);
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
return;
|
|
|
|
|
|
case ZM_PROCESS_WORKER:
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!is_int($id_or_name)) {
|
|
|
|
|
|
throw new ZMKnownException('E99999', 'worker_id必须为整数');
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
$file = _zm_pid_dir() . '/worker.' . $id_or_name . '.pid';
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (file_exists($file)) {
|
|
|
|
|
|
unlink($file);
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
return;
|
|
|
|
|
|
case ZM_PROCESS_USER:
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!is_string($id_or_name)) {
|
|
|
|
|
|
throw new ZMKnownException('E99999', 'process_name必须为字符串');
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
$file = _zm_pid_dir() . '/user.' . $id_or_name . '.pid';
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (file_exists($file)) {
|
|
|
|
|
|
unlink($file);
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
return;
|
|
|
|
|
|
case ZM_PROCESS_TASKWORKER:
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (!is_int($id_or_name)) {
|
|
|
|
|
|
throw new ZMKnownException('E99999', 'worker_id必须为整数');
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
$file = _zm_pid_dir() . '/taskworker.' . $id_or_name . '.pid';
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (file_exists($file)) {
|
|
|
|
|
|
unlink($file);
|
|
|
|
|
|
}
|
2022-03-13 22:46:22 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function start()
|
|
|
|
|
|
{
|
2021-06-16 00:17:30 +08:00
|
|
|
|
try {
|
|
|
|
|
|
self::$loaded_files = get_included_files();
|
|
|
|
|
|
self::$server->start();
|
2022-03-15 18:05:33 +08:00
|
|
|
|
zm_atomic('server_is_stopped')->set(1);
|
|
|
|
|
|
Console::log('zhamao-framework is stopped.');
|
2021-06-16 00:17:30 +08:00
|
|
|
|
} catch (Throwable $e) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
exit(zm_internal_errcode('E00011') . 'Framework has an uncaught ' . get_class($e) . ': ' . $e->getMessage() . PHP_EOL);
|
2021-06-16 00:17:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-15 18:05:33 +08:00
|
|
|
|
public static function printProps($out, $tty_width, $colorful = true)
|
|
|
|
|
|
{
|
|
|
|
|
|
$max_border = $tty_width < 65 ? $tty_width : 65;
|
|
|
|
|
|
if (LOAD_MODE == 0) {
|
|
|
|
|
|
echo Console::setColor("* Framework started with source mode.\n", $colorful ? 'yellow' : '');
|
|
|
|
|
|
}
|
|
|
|
|
|
echo str_pad('', $max_border, '=') . PHP_EOL;
|
|
|
|
|
|
|
|
|
|
|
|
$current_line = 0;
|
|
|
|
|
|
$line_width = [];
|
|
|
|
|
|
$line_data = [];
|
|
|
|
|
|
foreach ($out as $k => $v) {
|
|
|
|
|
|
start:
|
|
|
|
|
|
if (!isset($line_width[$current_line])) {
|
|
|
|
|
|
$line_width[$current_line] = $max_border - 2;
|
|
|
|
|
|
}
|
2022-03-20 16:23:07 +08:00
|
|
|
|
// Console::info("行宽[$current_line]:".$line_width[$current_line]);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if ($max_border >= 57) { // 很宽的时候,一行能放两个短行
|
2022-03-20 16:23:07 +08:00
|
|
|
|
if ($line_width[$current_line] == ($max_border - 2)) { // 空行
|
2022-03-15 18:05:33 +08:00
|
|
|
|
self::writeNoDouble($k, $v, $line_data, $line_width, $current_line, $colorful, $max_border);
|
|
|
|
|
|
} else { // 不是空行,已经有东西了
|
|
|
|
|
|
$tmp_line = $k . ': ' . $v;
|
2022-03-20 16:23:07 +08:00
|
|
|
|
// Console::info("[$current_line]即将插入后面的东西[".$tmp_line."]");
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (strlen($tmp_line) > $line_width[$current_line]) { // 地方不够,另起一行
|
|
|
|
|
|
$line_data[$current_line] = str_replace('| ', '', $line_data[$current_line]);
|
|
|
|
|
|
++$current_line;
|
|
|
|
|
|
goto start;
|
|
|
|
|
|
} // 地方够,直接写到后面并另起一行
|
|
|
|
|
|
$line_data[$current_line] .= $k . ': ';
|
|
|
|
|
|
if ($colorful) {
|
|
|
|
|
|
$line_data[$current_line] .= TermColor::color8(32);
|
|
|
|
|
|
}
|
|
|
|
|
|
$line_data[$current_line] .= $v;
|
|
|
|
|
|
if ($colorful) {
|
|
|
|
|
|
$line_data[$current_line] .= TermColor::RESET;
|
|
|
|
|
|
}
|
|
|
|
|
|
++$current_line;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else { // 不够宽,直接写单行
|
|
|
|
|
|
self::writeNoDouble($k, $v, $line_data, $line_width, $current_line, $colorful, $max_border);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
foreach ($line_data as $v) {
|
|
|
|
|
|
echo $v . PHP_EOL;
|
|
|
|
|
|
}
|
|
|
|
|
|
echo str_pad('', $max_border, '=') . PHP_EOL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static function getTtyWidth(): int
|
|
|
|
|
|
{
|
|
|
|
|
|
$size = exec('stty size');
|
|
|
|
|
|
if (empty($size)) {
|
|
|
|
|
|
return 65;
|
|
|
|
|
|
}
|
|
|
|
|
|
return (int) explode(' ', trim($size))[1];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static function loadFrameworkState()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!file_exists(DataProvider::getDataFolder() . '.state.json')) {
|
|
|
|
|
|
return [];
|
|
|
|
|
|
}
|
|
|
|
|
|
$r = json_decode(file_get_contents(DataProvider::getDataFolder() . '.state.json'), true);
|
|
|
|
|
|
if ($r === null) {
|
|
|
|
|
|
$r = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
return $r;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static function saveFrameworkState($data)
|
|
|
|
|
|
{
|
|
|
|
|
|
return file_put_contents(DataProvider::getDataFolder() . '.state.json', json_encode($data, 64 | 128 | 256));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static function printMotd($tty_width)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (file_exists(DataProvider::getSourceRootDir() . '/config/motd.txt')) {
|
|
|
|
|
|
$motd = file_get_contents(DataProvider::getSourceRootDir() . '/config/motd.txt');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$motd = file_get_contents(__DIR__ . '/../../config/motd.txt');
|
|
|
|
|
|
}
|
|
|
|
|
|
$motd = explode("\n", $motd);
|
|
|
|
|
|
foreach ($motd as $k => $v) {
|
|
|
|
|
|
$motd[$k] = substr($v, 0, $tty_width);
|
|
|
|
|
|
}
|
|
|
|
|
|
$motd = implode("\n", $motd);
|
|
|
|
|
|
echo $motd;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-07-09 01:38:30 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @noinspection PhpIncludeInspection
|
|
|
|
|
|
*/
|
2022-03-13 22:46:22 +08:00
|
|
|
|
private function loadServerEvents()
|
|
|
|
|
|
{
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if (Phar::running() !== '') {
|
2021-07-04 15:45:30 +08:00
|
|
|
|
ob_start();
|
2022-03-15 18:05:33 +08:00
|
|
|
|
include_once DataProvider::getFrameworkRootDir() . '/src/ZM/script_setup_loader.php';
|
2021-07-04 15:45:30 +08:00
|
|
|
|
$r = ob_get_clean();
|
|
|
|
|
|
$result_code = 0;
|
|
|
|
|
|
} else {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$r = exec(PHP_BINARY . ' ' . DataProvider::getFrameworkRootDir() . '/src/ZM/script_setup_loader.php', $output, $result_code);
|
2021-07-04 15:45:30 +08:00
|
|
|
|
}
|
2021-06-16 00:17:30 +08:00
|
|
|
|
if ($result_code !== 0) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
Console::error('Parsing code error!');
|
2021-06-16 00:17:30 +08:00
|
|
|
|
exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
$json = json_decode($r, true);
|
|
|
|
|
|
if (!is_array($json)) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
Console::warning(zm_internal_errcode('E00012') . 'Parsing @SwooleHandler and @OnSetup error!');
|
2021-06-16 00:17:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
$this->setup_events = $json;
|
2020-12-10 16:37:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-08-31 10:11:06 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 从全局配置文件里读取注入系统事件的类
|
|
|
|
|
|
* @throws ReflectionException
|
|
|
|
|
|
* @throws ReflectionException
|
|
|
|
|
|
*/
|
2022-03-13 22:46:22 +08:00
|
|
|
|
private function registerServerEvents()
|
|
|
|
|
|
{
|
2021-03-29 15:34:24 +08:00
|
|
|
|
$reader = new AnnotationReader();
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$all = ZMUtil::getClassesPsr4(FRAMEWORK_ROOT_DIR . '/src/ZM/Event/SwooleEvent/', 'ZM\\Event\\SwooleEvent');
|
2021-03-29 15:34:24 +08:00
|
|
|
|
foreach ($all as $v) {
|
|
|
|
|
|
$class = new $v();
|
|
|
|
|
|
$reflection_class = new ReflectionClass($class);
|
|
|
|
|
|
$anno_class = $reader->getClassAnnotation($reflection_class, SwooleHandler::class);
|
|
|
|
|
|
if ($anno_class !== null) { // 类名形式的注解
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$this->setup_events['event'][] = [
|
|
|
|
|
|
'class' => $v,
|
|
|
|
|
|
'method' => 'onCall',
|
|
|
|
|
|
'event' => $anno_class->event,
|
2021-05-08 10:02:41 +08:00
|
|
|
|
];
|
2021-03-29 15:34:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-15 18:05:33 +08:00
|
|
|
|
foreach (($this->setup_events['setup'] ?? []) as $v) {
|
|
|
|
|
|
Console::debug('Calling @OnSetup: ' . $v['class']);
|
|
|
|
|
|
$c = ZMUtil::getModInstance($v['class']);
|
|
|
|
|
|
$method = $v['method'];
|
|
|
|
|
|
$c->{$method}();
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
2021-05-08 10:02:41 +08:00
|
|
|
|
|
2022-03-15 18:05:33 +08:00
|
|
|
|
foreach ($this->setup_events['event'] as $v) {
|
|
|
|
|
|
self::$server->on($v['event'], function (...$param) use ($v) {
|
|
|
|
|
|
ZMUtil::getModInstance($v['class'])->{$v['method']}(...$param);
|
2021-05-08 10:02:41 +08:00
|
|
|
|
});
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 解析命令行的 $argv 参数们
|
|
|
|
|
|
* @param $args
|
2021-03-24 23:34:46 +08:00
|
|
|
|
* @param $add_port
|
2020-08-31 10:11:06 +08:00
|
|
|
|
*/
|
2022-03-13 22:46:22 +08:00
|
|
|
|
private function parseCliArgs($args, &$add_port)
|
|
|
|
|
|
{
|
2020-08-31 10:11:06 +08:00
|
|
|
|
$coroutine_mode = true;
|
|
|
|
|
|
global $terminal_id;
|
2021-02-21 22:17:34 +08:00
|
|
|
|
$terminal_id = uuidgen();
|
2020-08-31 10:11:06 +08:00
|
|
|
|
foreach ($args as $x => $y) {
|
2021-03-29 15:34:24 +08:00
|
|
|
|
if ($y) {
|
|
|
|
|
|
switch ($x) {
|
|
|
|
|
|
case 'worker-num':
|
2021-03-25 17:11:35 +08:00
|
|
|
|
if (intval($y) >= 1 && intval($y) <= 1024) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$this->server_set['worker_num'] = intval($y);
|
2021-03-25 17:11:35 +08:00
|
|
|
|
} else {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
Console::warning(zm_internal_errcode('E00013') . 'Invalid worker num! Turn to default value (' . ($this->server_set['worker_num'] ?? swoole_cpu_num()) . ')');
|
2021-03-25 17:11:35 +08:00
|
|
|
|
}
|
2021-03-29 15:34:24 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case 'task-worker-num':
|
2021-03-25 17:11:35 +08:00
|
|
|
|
if (intval($y) >= 1 && intval($y) <= 1024) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$this->server_set['task_worker_num'] = intval($y);
|
|
|
|
|
|
$this->server_set['task_enable_coroutine'] = true;
|
2021-03-25 17:11:35 +08:00
|
|
|
|
} else {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
Console::warning(zm_internal_errcode('E00013') . 'Invalid worker num! Turn to default value (0)');
|
2021-03-25 17:11:35 +08:00
|
|
|
|
}
|
2021-03-29 15:34:24 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case 'disable-coroutine':
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$coroutine_mode = false;
|
2021-03-29 15:34:24 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case 'debug-mode':
|
2022-03-15 18:05:33 +08:00
|
|
|
|
self::$argv['disable-safe-exit'] = true;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
$coroutine_mode = false;
|
|
|
|
|
|
$terminal_id = null;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
self::$argv['watch'] = true;
|
|
|
|
|
|
echo "* You are in debug mode, do not use in production!\n";
|
2021-03-29 15:34:24 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case 'daemon':
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$this->server_set['daemonize'] = 1;
|
|
|
|
|
|
Console::$theme = 'no-color';
|
|
|
|
|
|
Console::log('已启用守护进程,输出重定向到 ' . $this->server_set['log_file']);
|
2020-08-31 10:11:06 +08:00
|
|
|
|
$terminal_id = null;
|
2021-03-29 15:34:24 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case 'disable-console-input':
|
|
|
|
|
|
case 'no-interaction':
|
|
|
|
|
|
$terminal_id = null;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-error':
|
|
|
|
|
|
Console::setLevel(0);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-warning':
|
|
|
|
|
|
Console::setLevel(1);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-info':
|
|
|
|
|
|
Console::setLevel(2);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-verbose':
|
|
|
|
|
|
case 'verbose':
|
|
|
|
|
|
Console::setLevel(3);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-debug':
|
|
|
|
|
|
Console::setLevel(4);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-theme':
|
2020-08-31 10:11:06 +08:00
|
|
|
|
Console::$theme = $y;
|
2021-03-29 15:34:24 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case 'remote-terminal':
|
2021-03-27 16:30:15 +08:00
|
|
|
|
$add_port = true;
|
2021-03-29 15:34:24 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case 'show-php-ver':
|
|
|
|
|
|
default:
|
2022-03-20 16:23:07 +08:00
|
|
|
|
// Console::info("Calculating ".$x);
|
|
|
|
|
|
// dump($y);
|
2021-03-29 15:34:24 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$global_hook = ZMConfig::get('global', 'runtime')['swoole_coroutine_hook_flags'] ?? (SWOOLE_HOOK_ALL & (~SWOOLE_HOOK_CURL));
|
|
|
|
|
|
if ($coroutine_mode) {
|
|
|
|
|
|
Runtime::enableCoroutine(true, $global_hook);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Runtime::enableCoroutine(false, SWOOLE_HOOK_ALL);
|
|
|
|
|
|
}
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-13 22:46:22 +08:00
|
|
|
|
private static function writeNoDouble($k, $v, &$line_data, &$line_width, &$current_line, $colorful, $max_border)
|
|
|
|
|
|
{
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$tmp_line = $k . ': ' . $v;
|
2022-03-20 16:23:07 +08:00
|
|
|
|
// Console::info("写入[".$tmp_line."]");
|
|
|
|
|
|
if (strlen($tmp_line) > $line_width[$current_line]) { // 输出的内容太多了,以至于一行都放不下一个,要折行
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$title_strlen = strlen($k . ': ');
|
2021-03-02 21:24:31 +08:00
|
|
|
|
$content_len = $line_width[$current_line] - $title_strlen;
|
|
|
|
|
|
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$line_data[$current_line] = ' ' . $k . ': ';
|
|
|
|
|
|
if ($colorful) {
|
|
|
|
|
|
$line_data[$current_line] .= TermColor::color8(32);
|
|
|
|
|
|
}
|
2021-03-02 21:24:31 +08:00
|
|
|
|
$line_data[$current_line] .= substr($v, 0, $content_len);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if ($colorful) {
|
|
|
|
|
|
$line_data[$current_line] .= TermColor::RESET;
|
|
|
|
|
|
}
|
2021-03-02 21:24:31 +08:00
|
|
|
|
$rest = substr($v, $content_len);
|
|
|
|
|
|
++$current_line; // 带标题的第一行满了,折到第二行
|
|
|
|
|
|
do {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if ($colorful) {
|
|
|
|
|
|
$line_data[$current_line] = TermColor::color8(32);
|
|
|
|
|
|
}
|
|
|
|
|
|
$line_data[$current_line] .= ' ' . substr($rest, 0, $max_border - 2);
|
|
|
|
|
|
if ($colorful) {
|
|
|
|
|
|
$line_data[$current_line] .= TermColor::RESET;
|
|
|
|
|
|
}
|
2021-03-02 21:24:31 +08:00
|
|
|
|
$rest = substr($rest, $max_border - 2);
|
|
|
|
|
|
++$current_line;
|
|
|
|
|
|
} while ($rest > $max_border - 2); // 循环,直到放完
|
|
|
|
|
|
} else { // 不需要折行
|
2022-03-20 16:23:07 +08:00
|
|
|
|
// Console::info("不需要折行");
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$line_data[$current_line] = ' ' . $k . ': ';
|
|
|
|
|
|
if ($colorful) {
|
|
|
|
|
|
$line_data[$current_line] .= TermColor::color8(32);
|
|
|
|
|
|
}
|
2021-03-02 21:24:31 +08:00
|
|
|
|
$line_data[$current_line] .= $v;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if ($colorful) {
|
|
|
|
|
|
$line_data[$current_line] .= TermColor::RESET;
|
|
|
|
|
|
}
|
2021-03-02 21:24:31 +08:00
|
|
|
|
|
|
|
|
|
|
if ($max_border >= 57) {
|
|
|
|
|
|
if (strlen($tmp_line) >= intval(($max_border - 2) / 2)) { // 不需要折行,直接输出一个转下一行
|
2022-03-20 16:23:07 +08:00
|
|
|
|
// Console::info("不需要折行,直接输出一个转下一行");
|
2021-03-02 21:24:31 +08:00
|
|
|
|
++$current_line;
|
|
|
|
|
|
} else { // 输出很小,写到前面并分片
|
2022-03-20 16:23:07 +08:00
|
|
|
|
// Console::info("输出很小,写到前面并分片");
|
2021-03-02 21:24:31 +08:00
|
|
|
|
$space = intval($max_border / 2) - 2 - strlen($tmp_line);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$line_data[$current_line] .= str_pad('', $space);
|
|
|
|
|
|
$line_data[$current_line] .= '| '; // 添加分片
|
2021-03-02 21:24:31 +08:00
|
|
|
|
$line_width[$current_line] -= (strlen($tmp_line) + 3 + $space);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
++$current_line;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|