swoole.php
1 #!/bin/env php 2 <?php 3 /** 4 * 默认时区定义 5 */ 6 date_default_timezone_set('Asia/Shanghai'); 7 8 /** 9 * 设置错误报告模式 10 */ 11 error_reporting(0); 12 13 /** 14 * 设置默认区域 15 */ 16 setlocale(LC_ALL, "zh_CN.utf-8"); 17 18 /** 19 * 检测 PDO_MYSQL 20 */ 21 if (!extension_loaded('pdo_mysql')) { 22 exit('PDO_MYSQL extension is not installed' . PHP_EOL); 23 } 24 /** 25 * 检查exec 函数是否启用 26 */ 27 if (!function_exists('exec')) { 28 exit('exec function is disabled' . PHP_EOL); 29 } 30 /** 31 * 检查命令 lsof 命令是否存在 32 */ 33 exec("whereis lsof", $out); 34 if ($out[0] == 'lsof:') { 35 exit('lsof is not found' . PHP_EOL); 36 } 37 /** 38 * 定义项目根目录&swoole-task pid 39 */ 40 define('SWOOLE_PATH', __DIR__); 41 define('SWOOLE_TASK_PID_PATH', SWOOLE_PATH . DIRECTORY_SEPARATOR . 'Swoole' . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'swoole-task.pid'); 42 define('SWOOLE_TASK_NAME_PRE', 'swooleServ'); 43 44 /** 45 * 加载 swoole server 46 */ 47 include SWOOLE_PATH . DIRECTORY_SEPARATOR . 'Swoole' . DIRECTORY_SEPARATOR . 'SwooleServer.php'; 48 49 function portBind($port) { 50 $ret = []; 51 $cmd = "lsof -i :{$port}|awk '$1 != \"COMMAND\" {print $1, $2, $9}'"; 52 exec($cmd, $out); 53 if ($out) { 54 foreach ($out as $v) { 55 $a = explode(' ', $v); 56 list($ip, $p) = explode(':', $a[2]); 57 $ret[$a[1]] = [ 58 'cmd' => $a[0], 59 'ip' => $ip, 60 'port' => $p, 61 ]; 62 } 63 } 64 65 return $ret; 66 } 67 68 function servStart($host, $port, $daemon, $name) { 69 echo "正在启动 swoole-task 服务" . PHP_EOL; 70 if (!is_writable(dirname(SWOOLE_TASK_PID_PATH))) { 71 exit("swoole-task-pid文件需要目录的写入权限:" . dirname(SWOOLE_TASK_PID_PATH) . PHP_EOL); 72 } 73 if (file_exists(SWOOLE_TASK_PID_PATH)) { 74 $pid = explode("\n", file_get_contents(SWOOLE_TASK_PID_PATH)); 75 $cmd = "ps ax | awk '{ print $1 }' | grep -e \"^{$pid[0]}$\""; 76 exec($cmd, $out); 77 if (!empty($out)) { 78 exit("swoole-task pid文件 " . SWOOLE_TASK_PID_PATH . " 存在,swoole-task 服务器已经启动,进程pid为:{$pid[0]}" . PHP_EOL); 79 } else { 80 echo "警告:swoole-task pid文件 " . SWOOLE_TASK_PID_PATH . " 存在,可能swoole-task服务上次异常退出(非守护模式ctrl+c终止造成是最大可能)" . PHP_EOL; 81 unlink(SWOOLE_TASK_PID_PATH); 82 } 83 } 84 $bind = portBind($port); 85 if ($bind) { 86 foreach ($bind as $k => $v) { 87 if ($v['ip'] == '*' || $v['ip'] == $host) { 88 exit("端口已经被占用 {$host}:$port, 占用端口进程ID {$k}" . PHP_EOL); 89 } 90 } 91 } 92 unset($_SERVER['argv']); 93 $_SERVER['argc'] = 0; 94 echo "启动 swoole-task 服务成功" . PHP_EOL; 95 $server = new SwooleServer('127.0.0.1', 9501); 96 $server->run(); 97 //确保服务器启动后swoole-task-pid文件必须生成 98 /*if (!empty(portBind($port)) && !file_exists(SWOOLE_TASK_PID_PATH)) { 99 exit("swoole-task pid文件生成失败( " . SWOOLE_TASK_PID_PATH . ") ,请手动关闭当前启动的swoole-task服务检查原因" . PHP_EOL); 100 }*/ 101 } 102 103 function servStop($host, $port, $isRestart = false) { 104 echo "正在停止 swoole-task 服务" . PHP_EOL; 105 if (!file_exists(SWOOLE_TASK_PID_PATH)) { 106 exit('swoole-task-pid文件:' . SWOOLE_TASK_PID_PATH . '不存在' . PHP_EOL); 107 } 108 $pid = explode("\n", file_get_contents(SWOOLE_TASK_PID_PATH)); 109 $bind = portBind($port); 110 if (empty($bind) || !isset($bind[$pid[0]])) { 111 exit("指定端口占用进程不存在 port:{$port}, pid:{$pid[0]}" . PHP_EOL); 112 } 113 $cmd = "kill {$pid[0]}"; 114 exec($cmd); 115 do { 116 $out = []; 117 $c = "ps ax | awk '{ print $1 }' | grep -e \"^{$pid[0]}$\""; 118 exec($c, $out); 119 if (empty($out)) { 120 break; 121 } 122 } while (true); 123 //确保停止服务后swoole-task-pid文件被删除 124 if (file_exists(SWOOLE_TASK_PID_PATH)) { 125 unlink(SWOOLE_TASK_PID_PATH); 126 } 127 $msg = "执行命令 {$cmd} 成功,端口 {$host}:{$port} 进程结束" . PHP_EOL; 128 if ($isRestart) { 129 echo $msg; 130 } else { 131 exit($msg); 132 } 133 } 134 135 function servReload($host, $port, $isRestart = false) { 136 echo "正在平滑重启 swoole-task 服务" . PHP_EOL; 137 try { 138 $client = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); 139 $ret = $client->connect($host, $port); 140 if (empty($ret)) { 141 exit("{$host}:{$port} swoole-task服务不存在或者已经关闭" . PHP_EOL); 142 } else { 143 $client->send(json_encode(array('action' => 'reload'))); 144 } 145 $msg = "执行命令reload成功,端口 {$host}:{$port} 进程重启" . PHP_EOL; 146 if ($isRestart) { 147 echo $msg; 148 } else { 149 exit($msg); 150 } 151 } catch (Exception $e) { 152 exit($e->getMessage() . PHP_EOL . $e->getTraceAsString()); 153 } 154 } 155 156 function servClose($host, $port, $isRestart = false) { 157 echo "正在关闭 swoole-task 服务" . PHP_EOL; 158 try { 159 $client = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); 160 $ret = $client->connect($host, $port); 161 if (empty($ret)) { 162 exit("{$host}:{$port} swoole-task服务不存在或者已经关闭" . PHP_EOL); 163 } else { 164 $client->send(json_encode(array('action' => 'close'))); 165 } 166 //确保停止服务后swoole-task-pid文件被删除 167 if (file_exists(SWOOLE_TASK_PID_PATH)) { 168 unlink(SWOOLE_TASK_PID_PATH); 169 } 170 $msg = "执行命令close成功,端口 {$host}:{$port} 进程结束" . PHP_EOL; 171 if ($isRestart) { 172 echo $msg; 173 } else { 174 exit($msg); 175 } 176 } catch (\Exception $e) { 177 exit($e->getMessage() . PHP_EOL . $e->getTraceAsString()); 178 } 179 } 180 181 function servStatus($host, $port) { 182 echo "swoole-task {$host}:{$port} 运行状态" . PHP_EOL; 183 $pid = explode("\n", file_get_contents(SWOOLE_TASK_PID_PATH)); 184 $bind = portBind($port); 185 if (empty($bind) || !isset($bind[$pid[0]])) { 186 exit("指定端口占用进程不存在 port:{$port}, pid:{$pid[0]}" . PHP_EOL); 187 } 188 $client = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); 189 $ret = $client->connect($host, $port); 190 if (empty($ret)) { 191 exit("{$host}:{$port} swoole-task服务不存在或者已经停止" . PHP_EOL); 192 } else { 193 $client->send(json_encode(array('action' => 'status'))); 194 $out = $client->recv(); 195 $a = json_decode($out); 196 $b = array( 197 'start_time' => '服务器启动的时间', 198 'connection_num' => '当前连接的数量', 199 'accept_count' => '接受的连接数量', 200 'close_count' => '关闭的连接数量', 201 'tasking_num' => '当前正在排队的任务数', 202 'request_count' => '请求的连接数量', 203 'worker_request_count' => 'worker连接数量', 204 'task_process_num' => '任务进程数量' 205 ); 206 foreach ($a as $k1 => $v1) { 207 if ($k1 == 'start_time') { 208 $v1 = date("Y-m-d H:i:s", $v1); 209 } 210 echo $b[$k1] . ":\t$v1" . PHP_EOL; 211 } 212 } 213 exit(); 214 } 215 216 function servList() { 217 echo "本机运行的swoole-task服务进程" . PHP_EOL; 218 $cmd = "ps aux|grep " . SWOOLE_TASK_NAME_PRE . "|grep -v grep|awk '{print $1, $2, $6, $8, $9, $11}'"; 219 exec($cmd, $out); 220 if (empty($out)) { 221 exit("没有发现正在运行的swoole-task服务" . PHP_EOL); 222 } 223 echo "USER PID RSS(kb) STAT START COMMAND" . PHP_EOL; 224 foreach ($out as $v) { 225 echo $v . PHP_EOL; 226 } 227 exit(); 228 } 229 230 //可执行命令 231 $cmds = [ 232 'start', 233 'stop', 234 'restart', 235 'reload', 236 'close', 237 'status', 238 'list', 239 ]; 240 $shortopts = "dDh:p:n:"; 241 $longopts = [ 242 'help', 243 'daemon', 244 'nondaemon', 245 'host:', 246 'port:', 247 'name:', 248 ]; 249 $opts = getopt($shortopts, $longopts); 250 251 if (isset($opts['help']) || $argc < 2) { 252 echo <<<HELP 253 用法:php swoole.php 选项 ... 命令[start|stop|restart|reload|close|status|list] 254 管理swoole-task服务,确保系统 lsof 命令有效 255 如果不指定监听host或者port,使用配置参数 256 257 参数说明 258 --help 显示本帮助说明 259 -d, --daemon 指定此参数,以守护进程模式运行,不指定则读取配置文件值 260 -D, --nondaemon 指定此参数,以非守护进程模式运行,不指定则读取配置文件值 261 -h, --host 指定监听ip,例如 php swoole.php -h127.0.0.1 262 -p, --port 指定监听端口port, 例如 php swoole.php -h127.0.0.1 -p9520 263 -n, --name 指定服务进程名称,例如 php swoole.php -ntest start, 则进程名称为SWOOLE_TASK_NAME_PRE-name 264 启动swoole-task 如果不指定 host和port,读取默认配置 265 强制关闭swoole-task 必须指定port,没有指定host,关闭的监听端口是 *:port,指定了host,关闭 host:port端口 266 平滑关闭swoole-task 必须指定port,没有指定host,关闭的监听端口是 *:port,指定了host,关闭 host:port端口 267 强制重启swoole-task 必须指定端口 268 平滑重启swoole-task 必须指定端口 269 获取swoole-task 状态,必须指定port(不指定host默认127.0.0.1), tasking_num是正在处理的任务数量(0表示没有待处理任务) 270 271 HELP; 272 exit; 273 } 274 //参数检查 275 foreach ($opts as $k => $v) { 276 if (($k == 'h' || $k == 'host')) { 277 if (empty($v)) { 278 exit("参数 -h --host 必须指定值\n"); 279 } 280 } 281 if (($k == 'p' || $k == 'port')) { 282 if (empty($v)) { 283 exit("参数 -p --port 必须指定值\n"); 284 } 285 } 286 if (($k == 'n' || $k == 'name')) { 287 if (empty($v)) { 288 exit("参数 -n --name 必须指定值\n"); 289 } 290 } 291 } 292 293 //命令检查 294 $cmd = $argv[$argc - 1]; 295 if (!in_array($cmd, $cmds)) { 296 exit("输入命令有误 : {$cmd}, 请查看帮助文档\n"); 297 } 298 299 //监听ip 127.0.0.1,空读取配置文件 300 $host = '127.0.0.1'; 301 if (!empty($opts['h'])) { 302 $host = $opts['h']; 303 if (!filter_var($host, FILTER_VALIDATE_IP)) { 304 exit("输入host有误:{$host}"); 305 } 306 } 307 if (!empty($opts['host'])) { 308 $host = $opts['host']; 309 if (!filter_var($host, FILTER_VALIDATE_IP)) { 310 exit("输入host有误:{$host}"); 311 } 312 } 313 //监听端口,9501 读取配置文件 314 $port = 9501; 315 if (!empty($opts['p'])) { 316 $port = (int)$opts['p']; 317 if ($port <= 0) { 318 exit("输入port有误:{$port}"); 319 } 320 } 321 if (!empty($opts['port'])) { 322 $port = (int)$opts['port']; 323 if ($port <= 0) { 324 exit("输入port有误:{$port}"); 325 } 326 } 327 //进程名称 没有默认为 SWOOLE_TASK_NAME_PRE; 328 $name = SWOOLE_TASK_NAME_PRE; 329 if (!empty($opts['n'])) { 330 $name = $opts['n']; 331 } 332 if (!empty($opts['name'])) { 333 $name = $opts['n']; 334 } 335 //是否守护进程 -1 读取配置文件 336 $isdaemon = -1; 337 if (isset($opts['D']) || isset($opts['nondaemon'])) { 338 $isdaemon = 0; 339 } 340 if (isset($opts['d']) || isset($opts['daemon'])) { 341 $isdaemon = 1; 342 } 343 //启动swoole-task服务 344 if ($cmd == 'start') { 345 servStart($host, $port, $isdaemon, $name); 346 } 347 //强制停止swoole-task服务 348 if ($cmd == 'stop') { 349 if (empty($port)) { 350 exit("停止swoole-task服务必须指定port" . PHP_EOL); 351 } 352 servStop($host, $port); 353 } 354 //关闭swoole-task服务 355 if ($cmd == 'close') { 356 if (empty($port)) { 357 exit("停止swoole-task服务必须指定port" . PHP_EOL); 358 } 359 servClose($host, $port); 360 } 361 //强制重启swoole-task服务 362 if ($cmd == 'restart') { 363 if (empty($port)) { 364 exit("重启swoole-task服务必须指定port" . PHP_EOL); 365 } 366 echo "重启swoole-task服务" . PHP_EOL; 367 servStop($host, $port, true); 368 servStart($host, $port, $isdaemon, $name); 369 } 370 //平滑重启swoole-task服务 371 if ($cmd == 'reload') { 372 if (empty($port)) { 373 exit("平滑重启swoole-task服务必须指定port" . PHP_EOL); 374 } 375 echo "平滑重启swoole-task服务" . PHP_EOL; 376 servReload($host, $port, true); 377 } 378 //查看swoole-task服务状态 379 if ($cmd == 'status') { 380 if (empty($host)) { 381 $host = '127.0.0.1'; 382 } 383 if (empty($port)) { 384 exit("查看swoole-task服务必须指定port(host不指定默认使用127.0.0.1)" . PHP_EOL); 385 } 386 servStatus($host, $port); 387 } 388 //查看swoole-task服务进程列表 389 if ($cmd == 'list') { 390 servList(); 391 }
SwooleServer.php
1 <?php 2 3 /** 4 * Swoole服务端 5 */ 6 class SwooleServer { 7 8 private $_serv = null; 9 private $_setting = array(); 10 11 public function __construct($host = '0.0.0.0', $port = 9501) { 12 $this->_setting = array( 13 'host' => $host, 14 'port' => $port, 15 'env' => 'dev', //环境 dev|test|prod 16 'process_name' => SWOOLE_TASK_NAME_PRE, //swoole 进程名称 17 'worker_num' => 4, //一般设置为服务器CPU数的1-4倍 18 'task_worker_num' => 4, //task进程的数量 19 'task_ipc_mode' => 3, //使用消息队列通信,并设置为争抢模式 20 'task_max_request' => 10000, //task进程的最大任务数 21 'daemonize' => 1, //以守护进程执行 22 'max_request' => 10000, 23 'dispatch_mode' => 2, 24 'log_file' => SWOOLE_PATH . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'Runtime' . DIRECTORY_SEPARATOR . 'Logs' . DIRECTORY_SEPARATOR . 'Swoole' . date('Ymd') . '.log', //日志 25 ); 26 } 27 28 /** 29 * 运行swoole服务 30 */ 31 public function run() { 32 $this->_serv = new \swoole_server($this->_setting['host'], $this->_setting['port']); 33 $this->_serv->set(array( 34 'worker_num' => $this->_setting['worker_num'], 35 'task_worker_num' => $this->_setting['task_worker_num'], 36 'task_ipc_mode ' => $this->_setting['task_ipc_mode'], 37 'task_max_request' => $this->_setting['task_max_request'], 38 'daemonize' => $this->_setting['daemonize'], 39 'max_request' => $this->_setting['max_request'], 40 'dispatch_mode' => $this->_setting['dispatch_mode'], 41 'log_file' => $this->_setting['log_file'] 42 )); 43 $this->_serv->on('Start', array($this, 'onStart')); 44 $this->_serv->on('Connect', array($this, 'onConnect')); 45 $this->_serv->on('WorkerStart', array($this, 'onWorkerStart')); 46 $this->_serv->on('ManagerStart', array($this, 'onManagerStart')); 47 $this->_serv->on('WorkerStop', array($this, 'onWorkerStop')); 48 $this->_serv->on('Receive', array($this, 'onReceive')); 49 $this->_serv->on('Task', array($this, 'onTask')); 50 $this->_serv->on('Finish', array($this, 'onFinish')); 51 $this->_serv->on('Shutdown', array($this, 'onShutdown')); 52 $this->_serv->on('Close', array($this, 'onClose')); 53 $this->_serv->start(); 54 } 55 56 /** 57 * 设置swoole进程名称 58 * @param string $name swoole进程名称 59 */ 60 private function setProcessName($name) { 61 if (function_exists('cli_set_process_title')) { 62 cli_set_process_title($name); 63 } else { 64 if (function_exists('swoole_set_process_name')) { 65 swoole_set_process_name($name); 66 } else { 67 trigger_error(__METHOD__ . " failed. require cli_set_process_title or swoole_set_process_name."); 68 } 69 } 70 } 71 72 /** 73 * Server启动在主进程的主线程回调此函数 74 * @param $serv 75 */ 76 public function onStart($serv) { 77 if (!$this->_setting['daemonize']) { 78 echo 'Date:' . date('Y-m-d H:i:s') . "\t swoole_server master worker start\n"; 79 } 80 $this->setProcessName($this->_setting['process_name'] . '-master'); 81 //记录进程id,脚本实现自动重启 82 $pid = "{$serv->master_pid}\n{$serv->manager_pid}"; 83 file_put_contents(SWOOLE_TASK_PID_PATH, $pid); 84 } 85 86 /** 87 * worker start 加载业务脚本常驻内存 88 * @param $server 89 * @param $workerId 90 */ 91 public function onWorkerStart($serv, $workerId) { 92 if ($workerId >= $this->_setting['worker_num']) { 93 $this->setProcessName($this->_setting['process_name'] . '-task'); 94 } else { 95 $this->setProcessName($this->_setting['process_name'] . '-event'); 96 } 97 // 开启调试模式 建议开发阶段开启 部署阶段注释或者设为false 98 define('APP_DEBUG', True); 99 // 定义应用目录 100 define('APP_PATH', SWOOLE_PATH . DIRECTORY_SEPARATOR . 'Application' . DIRECTORY_SEPARATOR); 101 // 定义应用模式 102 define('APP_MODE', 'cli'); 103 // 引入ThinkPHP入口文件 104 require SWOOLE_PATH . DIRECTORY_SEPARATOR . 'ThinkPHP' . DIRECTORY_SEPARATOR . 'ThinkPHP.php'; 105 } 106 107 /** 108 * 监听连接进入事件 109 * @param $serv 110 * @param $fd 111 */ 112 public function onConnect($serv, $fd) { 113 if (!$this->_setting['daemonize']) { 114 echo 'Date:' . date('Y-m-d H:i:s') . "\t swoole_server connect[" . $fd . "]\n"; 115 } 116 } 117 118 /** 119 * worker 进程停止 120 * @param $server 121 * @param $workerId 122 */ 123 public function onWorkerStop($serv, $workerId) { 124 if (!$this->_setting['daemonize']) { 125 echo 'Date:' . date('Y-m-d H:i:s') . "\t swoole_server[{$serv->setting['process_name']} worker:{$workerId} shutdown\n"; 126 } 127 } 128 129 /** 130 * 当管理进程启动时调用 131 * @param $serv 132 */ 133 public function onManagerStart($serv) { 134 if (!$this->_setting['daemonize']) { 135 echo 'Date:' . date('Y-m-d H:i:s') . "\t swoole_server manager worker start\n"; 136 } 137 $this->setProcessName($this->_setting['process_name'] . '-manager'); 138 } 139 140 /** 141 * 此事件在Server结束时发生 142 */ 143 public function onShutdown($serv) { 144 if (file_exists(SWOOLE_TASK_PID_PATH)) { 145 unlink(SWOOLE_TASK_PID_PATH); 146 } 147 if (!$this->_setting['daemonize']) { 148 echo 'Date:' . date('Y-m-d H:i:s') . "\t swoole_server shutdown\n"; 149 } 150 } 151 152 /** 153 * 监听数据发送事件 154 * @param $serv 155 * @param $fd 156 * @param $from_id 157 * @param $data 158 */ 159 public function onReceive($serv, $fd, $from_id, $data) { 160 if (!$this->_setting['daemonize']) { 161 echo "Get Message From Client {$fd}:{$data}\n\n"; 162 } 163 $result = json_decode($data, true); 164 switch ($result['action']) { 165 case 'reload': //重启 166 $serv->reload(); 167 break; 168 case 'close': //关闭 169 $serv->shutdown(); 170 break; 171 case 'status': //状态 172 $serv->send($fd, json_encode($serv->stats())); 173 break; 174 default: 175 $serv->task($data); 176 break; 177 } 178 } 179 180 /** 181 * 监听连接Task事件 182 * @param $serv 183 * @param $task_id 184 * @param $from_id 185 * @param $data 186 */ 187 public function onTask($serv, $task_id, $from_id, $data) { 188 $result = json_decode($data, true); 189 //用TP处理各种逻辑 190 $serv->finish($data); 191 } 192 193 /** 194 * 监听连接Finish事件 195 * @param $serv 196 * @param $task_id 197 * @param $data 198 */ 199 public function onFinish($serv, $task_id, $data) { 200 if (!$this->_setting['daemonize']) { 201 echo "Task {$task_id} finish\n\n"; 202 echo "Result: {$data}\n\n"; 203 } 204 } 205 206 /** 207 * 监听连接关闭事件 208 * @param $serv 209 * @param $fd 210 */ 211 public function onClose($serv, $fd) { 212 if (!$this->_setting['daemonize']) { 213 echo 'Date:' . date('Y-m-d H:i:s') . "\t swoole_server close[" . $fd . "]\n"; 214 } 215 } 216 217 218 }
相关命令:
1、服务启动
#启动服务,不指定绑定端口和ip,则使用默认配置
php swoole.php start
#启动服务 指定ip 和 port
php swoole.php -h127.0.0.1 -p9501 start
#启动服务 守护进程模式
php swoole.php -h127.0.0.1 -p9501 -d start
#启动服务 非守护进程模式
php swoole.php -h127.0.0.1 -p9501 -D start
#启动服务 指定进程名称(显示进程名为 swooleServ-9510-[master|manager|event|task]
php swoole.php -h127.0.0.1 -p9501 -n 9501 start
2、强制服务停止
php swoole.php stop
php swoole.php -p9501 stop
php swoole.php -h127.0.0.1 -p9501 stop
3、关闭服务
php swoole.php close
php swoole.php -p9501 close
php swoole.php -h127.0.0.1 -p9501 close
4、强制服务重启
php swoole.php restart
php swoole.php -p9501 restart
php swoole.php -h127.0.0.1 -p9501 restart
5、平滑服务重启
php swoole.php reload
php swoole.php -p9501 reload
php swoole.php -h127.0.0.1 -p9501 reload
6、服务状态
php swoole.php status
php swoole.php -h127.0.0.1 -p9501 status
7、swoole-task所有启动实例进程列表(一台服务器swoole-task可以有多个端口绑定的实例)
php swoole.php list
Swoole-ThinkPHP.zip ( 1.14 MB )