public static function init() { self::$pid = \posix_getpid(); self::$ppid = \posix_getppid(); self::$child = array(); self::$alias = array(); self::$user_events = array(); self::$shm_to_pid = array(); self::$status['start_time'] = time(); // self::$shm_to_parent = -1; if (!self::$do_once) { // 初始化事件对象 if (extension_loaded('libevent')) { self::$events = new Libevent(); } else { self::$events = new Select(); } self::$shm = new Shm(__FILE__, 'a'); // 注册用户信号SIGUSR1处理函数 self::onSysEvent(SIGUSR1, EventInterface::EV_SIGNAL, array("\\cli\\proc\\Process", 'defaultSigusr1Cbk')); // 注册子进程退出处理函数 self::onSysEvent(SIGCHLD, EventInterface::EV_SIGNAL, array("\\cli\\proc\\Process", 'defaultSigchldCbk')); // 注册用户信号SIGUSR2处理函数 self::onSysEvent(SIGUSR2, EventInterface::EV_SIGNAL, array("\\cli\\proc\\Process", 'defaultSigusr2Cbk')); // 注册exit回调函数 register_shutdown_function(function () { Process::closeShm(); }); self::$do_once = true; } }
/** * socket事件回调函数 * @param [resource] $socket [服务器套接字] * @param [int] $ev_tag [事件标志] * @param [array] $args [回调参数] * @return [none] */ public function handle($socket = null, $ev_tag = null, $args = null) { // 回去远程命令 date_default_timezone_set('Asia/Shanghai'); if (null === $socket) { $cmds = new \stdClass(); $cmds->command = '_finished_'; } else { $rec_socket = stream_socket_accept($socket); $cmds = $this->_parseCmd($rec_socket); } if (empty($cmds)) { $cmds = array(); } $cmds = is_object($cmds) ? array($cmds) : $cmds; $log_file = Flight::conf()->get('cli.sys.rpc_logpath') . date('Y-m-d') . '.log'; // 逐个处理命令 foreach ($cmds as $cmd) { if (!isset($cmd->params)) { $cmd->params = array(); } $cur_cmd = $cmd; if ($cur_cmd->command == '_status_') { // 进程结束通知 $status = array(); $status['start_time'] = date('Y-m-d H:i:s', Process::$status['start_time']); $status['runing_list'] = $this->_runing_list; // $wait_cmd = array(); // array_walk($this->_cmd_queue, function($v, $k)use(&$wait_cmd){ // $wait_cmd[] = $v['command']; // }); $status['waiting_list'] = $this->_cmd_queue; fwrite($rec_socket, json_encode($status)); continue; } elseif ($cur_cmd->command == '_log_') { $tail_n = isset($cur_cmd->params[0]) ? (int) $cur_cmd->params[0] : 10; if (file_exists($log_file)) { $log_data = `tail -n {$tail_n} {$log_file}`; } fwrite($rec_socket, json_encode($log_data)); continue; } elseif ($cur_cmd->command == '_finished_') { // 进程结束通知 $this->_shell_count--; // 正在运行的进程计数自减 if ($queued_cmd = $this->shiftCmd()) { // 一个进程结束后,判断队列是否有正在等待的命令, // 有则唤起 $cur_cmd = $queued_cmd; } else { // 队列中没有等待命令,忽略 continue; } } else { if ($this->_shell_count >= Flight::conf()->get('cli.sys.maxprocess')) { // 正在运行的进程是否已经达到上限 // 是则插入等待队列,继续等待 $this->pushCmd($cur_cmd); continue; } else { $queued_cmd = $this->shiftCmd(); if (!empty($queued_cmd)) { // 队列中有等待的命令,先处理 $this->pushCmd($cur_cmd); $cur_cmd = $queued_cmd; } else { // 队列中没等待命令 } } } $process_cmd = $this->getProcessCmd($cur_cmd->command, $cur_cmd->params); if (false === $process_cmd) { continue; } $id = Process::fork($cur_cmd->command, $process_cmd['closure'], $process_cmd['params']); $log = date('H:i:s') . " start({$id}):" . json_encode($cur_cmd); $ret = `echo "{$log}" >> {$log_file}`; $this->_runing_list[$id] = $cur_cmd; $this->_spare_time[$id] = microtime(1); $this->_shell_count++; } }
<?php define('FLIGHT_ROOT', dirname(dirname(__DIR__)) . "/includes/flight"); define('BOOT_FILE', FLIGHT_ROOT . "/boot/boot.php"); require_once BOOT_FILE; use rpc\Rpcserver; use rpc\Rpcmaster; use flight\Flight; use cli\proc\Process; use cli\events\EventInterface; Flight::set('app.root', FLIGHT_ROOT); Process::init(); $server = new Rpcserver(); $server->schema('tcp')->host(Flight::conf()->get('cli.sys.localhost'))->port(Flight::conf()->get('cli.sys.localport'))->create(); $rpc_master = new Rpcmaster(); Process::onSysEvent($server->getSocket(), EventInterface::EV_READ, array($rpc_master, 'handle')); Process::loop();