瀏覽代碼

upgrade to 2.1.6

walkor 11 年之前
父節點
當前提交
6e8e29bf6d

+ 2 - 4
workerman/conf/conf.d/BusinessWorker.conf → applications/Demo/conf.d/BusinessWorker.conf

@@ -1,7 +1,5 @@
-;业务进程入口文件
-worker_file = ../applications/Demo/Bootstrap/BusinessWorker.php
-;BusinessWorker此项不用设置
-;listen = tcp://0.0.0.0:8483
+;业务进程入口文件,相对于本配置文件相对位置,可以只用绝对路径
+worker_file = ../Bootstrap/BusinessWorker.php
 ;启动多少服务进程
 start_workers = 32
 ;以哪个用户运行该进程,为了安全请使用权限较低的用户,例如www-data nobody

+ 2 - 8
workerman/conf/conf.d/Gateway.conf → applications/Demo/conf.d/Gateway.conf

@@ -1,5 +1,5 @@
-;进程入口文件
-worker_file = ../applications/Demo/Bootstrap/Gateway.php
+;进程入口文件,相对于本配置文件相对位置,可以只用绝对路径
+worker_file = ../Bootstrap/Gateway.php
 
 ;传输层协议及监听的ip端口
 listen = tcp://0.0.0.0:8480
@@ -17,12 +17,6 @@ user = root
 ;一般设置为协议头的长度,当请求到来时在dealInput中根据头部标识的数据包长度计算还有多少数据没接收完毕,并返回这个值
 preread_length = 1
 
-;接收缓冲区大小设置
-max_recv_buffer_size = 10485760
-
-;发送缓冲区大小设置
-max_send_buffer_size = 20971520
-
 ;不reload,当有reload命令时是否安全重启这个进程
 no_reload = 1
 

+ 1 - 1
workerman/conf/conf.d/StatisticProvider.conf → applications/Statistics/conf.d/StatisticProvider.conf

@@ -1,7 +1,7 @@
 ;==该worker的说明==
 ;提供查询统计信息数据接口
 ;进程入口文件
-worker_file = ../applications/Statistics/Bootstrap/StatisticProvider.php
+worker_file = ../Bootstrap/StatisticProvider.php
 ;监听ip及端口
 listen = tcp://0.0.0.0:55858
 ;启动多少进程,只开1个

+ 1 - 1
workerman/conf/conf.d/StatisticWeb.conf → applications/Statistics/conf.d/StatisticWeb.conf

@@ -1,6 +1,6 @@
 ;WebServer
 ;进程入口文件
-worker_file = ./Common/WebServer.php
+worker_file = WORKERMAN_ROOT_DIR/Common/WebServer.php
 ;监听的端口
 listen = tcp://0.0.0.0:55757
 ;http 协议 这里设置成短连接

+ 1 - 1
workerman/conf/conf.d/StatisticWorker.conf → applications/Statistics/conf.d/StatisticWorker.conf

@@ -1,7 +1,7 @@
 ;==该worker的说明==
 ;①收集汇总上报的统计信息
 ;进程入口文件
-worker_file = ../applications/Statistics/Bootstrap/StatisticWorker.php
+worker_file = ../Bootstrap/StatisticWorker.php
 ;监听ip及端口
 listen = udp://0.0.0.0:55656
 ;启动多少进程,这里可以只启动一个

+ 0 - 196
workerman/Common/FileMonitor.php

@@ -1,196 +0,0 @@
-<?php 
-require_once WORKERMAN_ROOT_DIR . 'Core/SocketWorker.php';
-/**
- * 
- * 用这个worker监控文件更新
- * 当文件更新后会给每个worker进程发送平滑重启信号
- * 做到文件更新自动加载到内存
- * 
-* @author walkor <walkor@workerman.net>
- */
-class FileMonitor extends Man\Core\AbstractWorker
-{
-    
-    /**
-     * 需要监控的文件
-     * @var array
-     */
-    protected $filesToInotify = array();
-    
-    /**
-     * 终端已经关闭
-     * @var bool
-     */
-    protected $terminalClosed = false;
-    
-    /**
-     * 该worker进程开始服务的时候会触发一次
-     * @return bool
-     */
-    public function start()
-    {
-        if(\Man\Core\Lib\Config::get('workerman.debug') != 1 || !\Man\Core\Master::getQueueId())
-        {
-            while(1)
-            {
-                if(!$this->hasShutDown())
-                {
-                    sleep(PHP_INT_MAX);
-                }
-                else
-                {
-                    exit(0);
-                }
-            }
-        }
-        $msg_type = $message = 0;
-        \Man\Core\Lib\Task::init();
-        \Man\Core\Lib\Task::add(1, array($this, 'sendSignalAndGetResult'));
-        \Man\Core\Lib\Task::add(1, array($this, 'checkFilesModify'));
-        \Man\Core\Lib\Task::add(1, array($this, 'checkTty'));
-        while(1)
-        {
-            $this->collectFiles(true);
-            if($this->hasShutDown())
-            {
-                exit(0);
-            }
-        }
-        return true;
-    }
-    
-    /**
-     * 发送文件上报信号,并收集文件列表
-     * @return void
-     */
-    public function sendSignalAndGetResult()
-    {
-        $this_pid = posix_getpid();
-        $pid_worker_map = $this->getPidWorkerMap();
-        foreach($pid_worker_map as $pid=>$worker_name)
-        {
-            if($pid != $this_pid)
-            {
-                posix_kill($pid, SIGUSR2);
-            }
-            $this->collectFiles();
-        }
-    }
-    
-    /**
-     * 从消息队列中获取要监控的文件列表
-     * @param bool $block
-     * @return void
-     */
-    protected function collectFiles($block = false)
-    {
-        $msg_type = $message = null;
-        $flag = $block ? 0 : MSG_IPC_NOWAIT;
-        if(@msg_receive(\Man\Core\Master::getQueueId(), self::MSG_TYPE_FILE_MONITOR, $msg_type, 10000, $message, true, $flag))
-        {
-            // 被排除的路径
-            $exclude_path = array();
-            // 因为配置可能会被更改,所以每次都会重新从配置中查找排除路径
-            $config_exclude_path = $this->getExcludeFiles();
-            foreach($config_exclude_path as $path)
-            {
-                if($real_path = realpath($path))
-                {
-                    $exclude_path[] = $real_path;
-                }
-            }
-            foreach($message as $file)
-            {
-                $is_exclude_file = false;
-                foreach($exclude_path as $path)
-                {
-                    // 是被排除的文件
-                    if(0  === strpos($file, $path))
-                    {
-                        $is_exclude_file = true;
-                        break;
-                    }
-                }
-                if(!$is_exclude_file && !isset($this->filesToInotify[$file]))
-                {
-                    $stat = @stat($file);
-                    $mtime = isset($stat['mtime']) ? $stat['mtime'] : 0;
-                    $this->filesToInotify[$file] = $mtime;
-                }
-            }
-        }
-    }
-
-    /**
-     * 发送信号给所有worker
-     * @param integer $signal
-     * @return void
-     */
-    public function sendSignalToAllWorker($signal)
-    {
-        $this_pid = posix_getpid();
-        $pid_worker_map = $this->getPidWorkerMap();
-        foreach($pid_worker_map as $pid=>$worker_name)
-        {
-            if($pid != $this_pid)
-            {
-                posix_kill($pid, $signal);
-            }
-        }
-    }
-    
-    /**
-     * 检查文件更新时间,如果有更改则平滑重启服务(开发的时候用到)
-     * @return void
-     */
-    public function checkFilesModify()
-    {
-        $has_send_signal = false;
-        foreach($this->filesToInotify as $file=>$mtime)
-        {
-            clearstatcache();
-            $stat = @stat($file);
-            if(false === $stat)
-            {
-                unset($this->filesToInotify[$file]);
-                continue;
-            }
-            $mtime_now = $stat['mtime'];
-            if($mtime != $mtime_now) 
-            {
-                $this->filesToInotify[$file] = $mtime_now;
-                if(!$has_send_signal)
-                {
-                    \Man\Core\Lib\Log::add("$file updated and reload workers");
-                    $this->sendSignalToAllWorker(SIGHUP);
-                    $has_send_signal = true;
-                }
-            }
-        }
-    }
-    
-    /**
-     * 检查控制终端是否已经关闭, 如果控制终端关闭,则停止打印数据到终端(发送平滑重启信号)
-     * @return void
-     */
-    public function checkTty()
-    {
-        if(!$this->terminalClosed && !@posix_ttyname(STDOUT))
-        {
-            $this->resetFd();
-            // 日志
-            $this->notice("terminal closed and reset workers fd");
-            // worker重启时会检测终端是否关闭
-            $this->sendSignalToAllWorker(SIGTTOU);
-            // 设置标记
-            $this->terminalClosed = true;
-        }
-    }
-    
-    protected function getExcludeFiles()
-    {
-        $exclude_path = \Man\Core\Lib\Config::get($this->workerName.'.exclude_path');
-        return (array)$exclude_path;
-    }
-    
-} 

+ 8 - 5
workerman/Common/Monitor.php

@@ -70,7 +70,7 @@ class Monitor extends Man\Core\SocketWorker
      * worker占用内存限制 单位KB
      * @var integer
      */
-    const DEFAULT_MEM_LIMIT = 83886;
+    const DEFAULT_MEM_LIMIT = 124000;
     
     /**
      * 上次获得的主进程信息 
@@ -121,7 +121,7 @@ class Monitor extends Man\Core\SocketWorker
         \Man\Core\Lib\Task::add(self::CHECK_MASTER_PROCESS_TIME_LONG, array($this, 'checkMasterProcess'));
         \Man\Core\Lib\Task::add(self::CHECK_MASTER_STATUS_TIME_LONG, array($this, 'checkMasterStatus'));
         \Man\Core\Lib\Task::add(self::CHECK_MASTER_STATUS_TIME_LONG, array($this, 'checkMemUsage'));
-        
+
         // 添加accept事件
         $this->event->add($this->mainSocket,  \Man\Core\Events\BaseEvent::EV_READ, array($this, 'onAccept'));
         
@@ -142,7 +142,7 @@ class Monitor extends Man\Core\SocketWorker
         if($fd)
         {
             $this->currentDealFd = (int)$fd;
-            if($this->getRemoteIp() != '127.0.0.1')
+            if($this->protocol != 'unix' && $this->getRemoteIp() != '127.0.0.1' )
             {
                 $this->sendToClient("Password\n");
             }
@@ -231,6 +231,10 @@ class Monitor extends Man\Core\SocketWorker
                 $pid_worker_name_map = $this->getPidWorkerMap();
                 foreach($worker_pids as $worker_name=>$pid_array)
                 {
+                    if('Monitor' === $worker_name)
+                    {
+                        continue;
+                    }
                     if($this->maxWorkerNameLength < strlen($worker_name))
                     {
                         $this->maxWorkerNameLength = strlen($worker_name);
@@ -631,5 +635,4 @@ class Monitor extends Man\Core\SocketWorker
     {
         return is_file($path) ? unlink($path) : array_map(array($this, 'recursiveDelete'),glob($path.'/*')) == rmdir($path);
     }
-    
-} 
+} 

+ 12 - 7
workerman/Core/AbstractWorker.php

@@ -1,6 +1,8 @@
 <?php 
 namespace Man\Core;
-require_once WORKERMAN_ROOT_DIR . 'Core/Events/Select.php';
+
+use \Man\Core\Lib\Config;
+use \Man\Core\Lib\Log;
 
 /**
  * 抽象Worker类
@@ -258,9 +260,9 @@ abstract class AbstractWorker
      */
     protected function notice($str, $display = true)
     {
-        $str = 'Worker['.get_class($this).']:'.$str;
-        Lib\Log::add($str);
-        if($display && Lib\Config::get('workerman.debug') == 1)
+        $str = 'Worker['.get_class($this).':' . posix_getpid() . ']:'.$str;
+        Log::add($str);
+        if($display && Config::get('workerman.debug') == 1)
         {
             echo $str."\n";
         }
@@ -272,12 +274,15 @@ abstract class AbstractWorker
      */
     protected function resetFd()
     {
+        if(\Man\Core\Master::hasResetFd())
+        {
+            return;
+        }
         global $STDOUT, $STDERR;
         @fclose(STDOUT);
         @fclose(STDERR);
-        // 将标准输出重定向到/dev/null
-        $STDOUT = fopen('/dev/null',"rw+");
-        $STDERR = fopen('/dev/null',"rw+");
+        $STDOUT = fopen('/dev/null',"a");
+        $STDERR = fopen('/dev/null',"a");
     }
     
 }

+ 0 - 1
workerman/Core/Events/Libevent.php

@@ -1,6 +1,5 @@
 <?php 
 namespace Man\Core\Events;
-require_once WORKERMAN_ROOT_DIR . 'Core/Events/interfaces.php';
 /**
  * 
  * libevent事件轮询库的封装

+ 5 - 38
workerman/Core/Events/Select.php

@@ -1,6 +1,5 @@
 <?php 
 namespace Man\Core\Events;
-require_once WORKERMAN_ROOT_DIR . 'Core/Events/interfaces.php';
 /**
  * 
  * select 轮询封装
@@ -36,38 +35,6 @@ class Select implements BaseEvent
     public $writeFds = array();
     
     /**
-     * 搞个fd,避免 $readFds $writeFds 都为空时select 失败
-     * @var resource
-     */
-    public $channel = null;
-    
-    /**
-     *  读超时 毫秒
-     * @var integer
-     */
-    protected $readTimeout = 1000;
-    
-    /**
-     * 写超时 毫秒
-     * @var integer
-     */
-    protected $writeTimeout = 1000;
-    
-    /**
-     * 构造函数 创建一个管道,避免select空fd
-     * @return void
-     */
-    public function __construct()
-    {
-        $this->channel = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
-        if($this->channel)
-        {
-            stream_set_blocking($this->channel[0], 0);
-            $this->readFds[0] = $this->channel[0];
-        }
-    }
-   
-    /**
      * 添加事件
      * @see \Man\Core\Events\BaseEvent::add()
      */
@@ -151,14 +118,16 @@ class Select implements BaseEvent
         {
             $read = $this->readFds;
             $write = $this->writeFds;
-            // stream_select false:出错 0:超时
-            if(!($ret = @stream_select($read, $write, $e, 1)))
+            // 触发信号处理函数
+            pcntl_signal_dispatch();
+            // stream_select false:出错 ; 0:超时
+            if(!($ret = @stream_select($read, $write, $e, PHP_INT_MAX)))
             {
                 // 超时
                 if($ret === 0)
                 {
                 }
-                // 被系统调用或者信号打断
+                // 被信号打断
                 elseif($ret === false)
                 {
                 }
@@ -166,8 +135,6 @@ class Select implements BaseEvent
                 pcntl_signal_dispatch();
                 continue;
             }
-            // 触发信号处理函数
-            pcntl_signal_dispatch();
             
             // 检查所有可读描述符
             foreach($read as $fd)

+ 4 - 0
workerman/Core/Lib/Checker.php

@@ -151,6 +151,10 @@ class Checker
         echo "\033[47;30muser\033[0m",str_pad('', self::$maxUserNameLength+2-strlen('user')), "\033[47;30mworker\033[0m",str_pad('', self::$maxWorkerNameLength+2-strlen('worker')), "\033[47;30mlisten\033[0m",str_pad('', self::$maxListenLength+2-strlen('listen')), "\033[47;30mprocesses\033[0m",str_pad('', self::$maxProcessCountLength+2-strlen('processes')),"\033[47;30m","status\033[0m\n";
         foreach (Config::getAllWorkers() as $worker_name=>$config)
         {
+            if($worker_name == 'Monitor')
+            {
+                continue;
+            }
             if(isset($config['user']))
             {
                 $worker_user = $config['user'];

+ 55 - 2
workerman/Core/Lib/Config.php

@@ -9,6 +9,12 @@ namespace Man\Core\Lib;
 class Config
 {
     /**
+     * 默认应用配置匹配路径
+     * @var string
+     */
+    const DEFAULT_CONFD_PATH = './conf/conf.d/*.conf';
+    
+    /**
      * 配置文件名称
      * @var string
      */
@@ -32,18 +38,56 @@ class Config
      */
     private function __construct()
      {
+         // 主配置位置
         $config_file = WORKERMAN_ROOT_DIR . '/conf/workerman.conf';
         if (!file_exists($config_file)) 
         {
             throw new \Exception('Configuration file "' . $config_file . '" not found');
         }
+        // 载入主配置
         self::$config['workerman'] = self::parseFile($config_file);
+        self::$config['workerman']['log_dir'] = isset(self::$config['workerman']['log_dir']) ? self::$config['workerman']['log_dir'] : WORKERMAN_ROOT_DIR.'/logs';
         self::$configFile = realpath($config_file);
-        foreach(glob(WORKERMAN_ROOT_DIR . 'conf/conf.d/*.conf') as $config_file)
+        // 寻找应用配置
+        $conf_d = isset(self::$config['workerman']['include']) ? self::$config['workerman']['include'] : self::DEFAULT_CONFD_PATH;
+        $conf_d = WORKERMAN_ROOT_DIR . self::$config['workerman']['include'];
+        foreach(glob($conf_d) as $config_file)
         {
             $worker_name = basename($config_file, '.conf');
-            self::$config[$worker_name] = self::parseFile($config_file);
+            $config_data = self::parseFile($config_file);
+            if(!isset($config_data['enable']) || $config_data['enable'] )
+            {
+                self::$config[$worker_name] = self::parseFile($config_file);
+            }
+            else 
+            {
+                continue;
+            }
+            // 支持 WORKERMAN_ROOT_DIR 配置
+            array_walk_recursive(self::$config[$worker_name], array('\Man\Core\Lib\Config', 'replaceWORKERMAN_ROOT_DIR'));
+            // 不是以 / 开头代表相对路径,相对于配置文件的路径,找出绝对路径
+            if(0 !== strpos(self::$config[$worker_name]['worker_file'], '/'))
+            {
+                self::$config[$worker_name]['worker_file'] =dirname($config_file).'/'.self::$config[$worker_name]['worker_file'];
+            }
         }
+        // 整理Monitor配置
+        self::$config['Monitor'] = self::$config['workerman']['Monitor'];
+        unset(self::$config['workerman']['Monitor']);
+        self::$config['Monitor']['worker_file']= 'Common/Monitor.php';
+        self::$config['Monitor']['persistent_connection'] = 1;
+        self::$config['Monitor']['start_workers'] = 1;
+        self::$config['Monitor']['user'] = 'root';
+        self::$config['Monitor']['preread_length'] = 8192;
+        self::$config['Monitor']['exclude_path'] = isset(self::$config['Monitor']['exclude_path']) ?  array_merge(self::$config['Monitor']['exclude_path'], get_included_files()) : get_included_files();
+        self::$config['Monitor']['exclude_path'][] = self::$config['workerman']['log_dir'];
+        if(!isset(self::$config['Monitor']['listen']))
+        {
+            $socket_file = WORKERMAN_ROOT_DIR.'bin/unixsock';
+            self::$config['Monitor']['listen'] = 'unix://' . $socket_file;
+        }
+        // 支持 WORKERMAN_ROOT_DIR 配置
+        array_walk_recursive(self::$config['Monitor'], array('\Man\Core\Lib\Config', 'replaceWORKERMAN_ROOT_DIR'));
     }
     
     /**
@@ -113,4 +157,13 @@ class Config
         self::instance();
     }
     
+    /**
+     * 替换WORKERMAN_ROOT_DIR为真实WORKERMAN_ROOT_DIR常量表示的路径
+     * @param mixed $val
+     */
+    public static function replaceWORKERMAN_ROOT_DIR(&$val)
+    {
+        $val = str_replace('WORKERMAN_ROOT_DIR', WORKERMAN_ROOT_DIR, $val);
+    }
+    
 }

+ 20 - 4
workerman/Core/Lib/Task.php

@@ -33,7 +33,6 @@ class Task
      */
     public static function init($event = null)
     {
-        pcntl_alarm(1);
         if($event)
         {
             $event->add(SIGALRM, \Man\Core\Events\BaseEvent::EV_SIGNAL, array('\Man\Core\Lib\Task', 'signalHandle'));
@@ -70,11 +69,21 @@ class Task
         {
             return false;
         }
-        if(!is_callable($func) && class_exists('Log'))
+        if(!is_callable($func))
         {
-            \Man\Core\Lib\Log::add(var_export($func, true). "not callable\n");
+            if(class_exists('\Man\Core\Lib\Log'))
+            {
+                \Man\Core\Lib\Log::add(var_export($func, true). "not callable\n");
+            }
             return false;
         }
+        
+        // 有任务时才出发计时器
+        if(empty(self::$tasks))
+        {
+            pcntl_alarm(1);
+        }
+        
         $time_now = time();
         $run_time = $time_now + $time_long;
         if(!isset(self::$tasks[$run_time]))
@@ -111,7 +120,14 @@ class Task
                     $task_args = $one_task[1];
                     $persistent = $one_task[2];
                     $time_long = $one_task[3];
-                    call_user_func_array($task_func, $task_args);
+                    try 
+                    {
+                        call_user_func_array($task_func, $task_args);
+                    }
+                    catch(\Exception $e)
+                    {
+                        echo $e;
+                    }
                     // 持久的放入下一个任务队列
                     if($persistent)
                     {

+ 119 - 33
workerman/Core/Master.php

@@ -1,6 +1,12 @@
 <?php 
 namespace Man\Core;
 
+use \Man\Core\Lib\Task;
+use \Man\Core\Lib\Config;
+use \Man\Core\Lib\Checker;
+use \Man\Core\Lib\Log;
+
+
 if(!defined('WORKERMAN_ROOT_DIR'))
 {
     define('WORKERMAN_ROOT_DIR', realpath(__DIR__."/../../")."/");
@@ -11,6 +17,11 @@ require_once WORKERMAN_ROOT_DIR . 'Core/Lib/Config.php';
 require_once WORKERMAN_ROOT_DIR . 'Core/Lib/Task.php';
 require_once WORKERMAN_ROOT_DIR . 'Core/Lib/Log.php';
 require_once WORKERMAN_ROOT_DIR . 'Core/Lib/Mutex.php';
+require_once WORKERMAN_ROOT_DIR . 'Core/Events/interfaces.php';
+require_once WORKERMAN_ROOT_DIR . 'Core/Events/Select.php';
+require_once WORKERMAN_ROOT_DIR . 'Core/Events/Libevent.php';
+require_once WORKERMAN_ROOT_DIR . 'Core/AbstractWorker.php';
+require_once WORKERMAN_ROOT_DIR . 'Core/SocketWorker.php';
 
 /**
  * 
@@ -144,6 +155,17 @@ class Master
     protected static $masterPid = 0;
     
     /**
+     * 终端是否关闭
+     * @var bool
+     */
+    protected static $terminalClosed = false;
+
+    /**
+     * 是否已经重定向了标准输出
+     * @var bool
+     */
+    protected static $hasResetStd = false;
+    /**
      * server统计信息 ['start_time'=>time_stamp, 'worker_exit_code'=>['worker_name1'=>[code1=>count1, code2=>count2,..], 'worker_name2'=>[code3=>count3,...], ..] ]
      * @var array
      */
@@ -179,7 +201,7 @@ class Master
         // 标记服务状态为运行中
         self::$serviceStatus = self::STATUS_RUNNING;
         // 初始化任务
-        \Man\Core\Lib\Task::init();
+        Task::init();
         // 关闭标准输出
         self::resetStdFd();
         // 主循环
@@ -203,7 +225,7 @@ class Master
         }
         
         // 获取配置文件
-        $config_path = Lib\Config::$configFile;
+        $config_path = Config::$configFile;
     
         // 设置进程名称,如果支持的话
         self::setProcTitle(self::NAME.':master with-config:' . $config_path);
@@ -224,22 +246,22 @@ class Master
     public static function checkEnv()
     {
         // 检查PID文件
-        Lib\Checker::checkPidFile();
+        Checker::checkPidFile();
         
         // 检查扩展支持情况
-        Lib\Checker::checkExtension();
+        Checker::checkExtension();
         
         // 检查函数禁用情况
-        Lib\Checker::checkDisableFunction();
+        Checker::checkDisableFunction();
         
         // 检查log目录是否可读
-        Lib\Log::init();
+        Log::init();
         
         // 检查配置和语法错误等
-        Lib\Checker::checkWorkersConfig();
+        Checker::checkWorkersConfig();
         
         // 检查文件限制
-        Lib\Checker::checkLimit();
+        Checker::checkLimit();
     }
     
     /**
@@ -321,7 +343,7 @@ class Master
     protected static function createListeningSockets()
     {
         // 循环读取配置创建socket
-        foreach (Lib\Config::getAllWorkers() as $worker_name=>$config)
+        foreach (Config::getAllWorkers() as $worker_name=>$config)
         {
             if(isset($config['listen']))
             {
@@ -340,7 +362,7 @@ class Master
                 }
                 if(!self::$listenedSocketsArray[$worker_name])
                 {
-                    Lib\Log::add("can not create socket {$config['listen']} info:{$error_no} {$error_msg}\tServer start fail");
+                    Log::add("can not create socket {$config['listen']} info:{$error_no} {$error_msg}\tServer start fail");
                     exit("\n\033[31;40mCan not create socket {$config['listen']} {$error_msg}\033[0m\n\n\033[31;40mWorkerman start fail\033[0m\n\n");
                 }
             }
@@ -355,7 +377,7 @@ class Master
     protected static function spawnWorkers()
     {
         // 生成一定量的worker进程
-        foreach (Lib\Config::getAllWorkers() as $worker_name=>$config)
+        foreach (Config::getAllWorkers() as $worker_name=>$config)
         {
             // 初始化
             if(empty(self::$workerPidMap[$worker_name]))
@@ -405,7 +427,7 @@ class Master
             self::ignoreSignal();
             
             // 清空任务
-            Lib\Task::delAll();
+            Task::delAll();
             
             // 关闭不用的监听socket
             foreach(self::$listenedSocketsArray as $tmp_worker_name => $tmp_socket)
@@ -417,26 +439,23 @@ class Master
             }
     
             // 尝试以指定用户运行worker进程
-            if($worker_user = Lib\Config::get($worker_name . '.user'))
+            if($worker_user = Config::get($worker_name . '.user'))
             {
                 self::setProcUser($worker_user);
             }
             
             // 关闭输出
-            self::resetStdFd(Lib\Config::get($worker_name.'.no_debug'));
+            self::resetStdFd(Config::get($worker_name.'.no_debug'));
     
             // 尝试设置子进程进程名称
             self::setWorkerProcTitle($worker_name);
     
-            // 包含必要文件
-            require_once WORKERMAN_ROOT_DIR . 'Core/SocketWorker.php';
-            
             // 查找worker文件
-            $worker_file = \Man\Core\Lib\Config::get($worker_name.'.worker_file');
+            $worker_file = Config::get($worker_name.'.worker_file');
             $class_name = basename($worker_file, '.php');
             
             // 如果有语法错误 sleep 5秒 避免狂刷日志
-            if(\Man\Core\Lib\Checker::checkSyntaxError($worker_file, $class_name))
+            if(Checker::checkSyntaxError($worker_file, $class_name))
             {
                 sleep(5);
             }
@@ -530,14 +549,14 @@ class Master
                 break;
             // 平滑重启server信号
             case SIGHUP:
-                Lib\Config::reload();
+                Config::reload();
                 self::notice("Workerman reloading");
                 $pid_worker_name_map = self::getPidWorkerNameMap();
                 $pids_to_restart = array();
                 foreach($pid_worker_name_map as $pid=>$worker_name)
                 {
                     // 如果对应进程配置了不热启动则不重启对应进程
-                    if(Lib\Config::get($worker_name.'.no_reload'))
+                    if(Config::get($worker_name.'.no_reload'))
                     {
                         // 发送reload信号,以便触发onReload方法
                         posix_kill($pid, SIGHUP);
@@ -586,6 +605,8 @@ class Master
             sleep(1);
             // 检查是否有进程退出
             self::checkWorkerExit();
+            // 检查终端是否关闭
+            self::checkTty();
             // 触发信号处理
             pcntl_signal_dispatch();
         }
@@ -734,7 +755,7 @@ class Master
             {
                 self::$pidsToRestart[$pid] = time();
                 posix_kill($pid, SIGHUP);
-                Lib\Task::add(self::KILL_WORKER_TIME_LONG, array('\Man\Core\Master', 'forceKillWorker'), array($pid), false);
+                Task::add(self::KILL_WORKER_TIME_LONG, array('\Man\Core\Master', 'forceKillWorker'), array($pid), false);
                 break;
             }
         }
@@ -770,7 +791,7 @@ class Master
         self::$serviceStatus = self::STATUS_SHUTDOWN;
     
         // killWorkerTimeLong 秒后如果还没停止则强制杀死所有进程
-        Lib\Task::add(self::KILL_WORKER_TIME_LONG, array('\Man\Core\Master', 'stopAllWorker'), array(true), false);
+        Task::add(self::KILL_WORKER_TIME_LONG, array('\Man\Core\Master', 'stopAllWorker'), array(true), false);
     
         // 停止所有worker
         self::stopAllWorker();
@@ -867,21 +888,51 @@ class Master
      */
     protected static function resetStdFd($force = false)
     {
+        // 已经重定向了标准输出
+        if(self::$hasResetStd)
+        {
+            return;
+        }
+        // 将标准输出重定向到$stdout_file
+        global $STDOUT, $STDERR;
+        $stdout_file = Config::get('workerman.stdout_file');
+        if($stdout_file)
+        {
+            $handle = fopen($stdout_file,"a");
+            if($handle) 
+            {
+                unset($handle);
+                @fclose(STDOUT);
+                @fclose(STDERR);
+                $STDOUT = fopen($stdout_file,"a");
+                $STDERR = fopen($stdout_file,"a");
+                self::$hasResetStd = true;
+                return;
+            }
+        }
         // 如果此进程配置是no_debug,则关闭输出
         if(!$force)
         {
-            // 开发环境不关闭标准输出,用于调试
-            if(Lib\Config::get('workerman.debug') == 1 && posix_ttyname(STDOUT))
+            // 没有设置 stdout_file并且debug开启并且终端没有关闭则不关闭标准输出,用于调试
+            if(Config::get('workerman.debug') == 1 && @posix_ttyname(STDOUT))
             {
-                return;
+                return ;
             }
         }
-        global $STDOUT, $STDERR;
         @fclose(STDOUT);
         @fclose(STDERR);
-        // 将标准输出重定向到/dev/null
-        $STDOUT = fopen('/dev/null',"rw+");
-        $STDERR = fopen('/dev/null',"rw+");
+        $STDOUT = fopen('/dev/null',"a");
+        $STDERR = fopen('/dev/null',"a");
+        self::$hasResetStd = true;
+    }
+    
+    /**
+     * 是否已经重置了fd
+     * @return boolean
+     */
+    public static function hasResetFd()
+    {
+        return self::$hasResetStd;
     }
     
     /**
@@ -946,11 +997,11 @@ class Master
             return $context;
         }
         // 读取worker的backlog
-        $backlog = (int)Lib\Config::get($worker_name . '.backlog');
+        $backlog = (int)Config::get($worker_name . '.backlog');
         // 没有设置或者不合法则尝试使用workerman.conf中的backlog设置
         if($backlog <= 0)
         {
-            $backlog = (int)Lib\Config::get('workerman.backlog');
+            $backlog = (int)Config::get('workerman.backlog');
         }
         // 都没设置backlog,使用默认值
         if($backlog <= 0)
@@ -969,6 +1020,41 @@ class Master
     }
     
     /**
+     * 检查控制终端是否已经关闭, 如果控制终端关闭,则停止打印数据到终端
+     * @return void
+     */
+    public static function checkTty()
+    {
+        // 已经重置了fd,就不检查终端是否关闭,因为不会打印东西到屏幕了
+        if(self::$hasResetStd)
+        {
+            return;
+        }
+        // 没开启debug不打印数据到屏幕,不检测终端是否关闭
+        if(!Config::get('workerman.debug'))
+        {
+            return;
+        }
+        // 检测终端是否关闭
+        if(!self::$terminalClosed && !@posix_ttyname(STDOUT))
+        {
+            self::resetStdFd(true);
+            // 日志
+            self::notice("terminal closed and reset workers fd");
+            // 获取所有子进程pid
+            $all_worker_pid = self::getPidWorkerNameMap();
+            // 向所有子进程发送重置标准输入输出信号
+            foreach($all_worker_pid as $pid=>$worker_name)
+            {
+                // 发送SIGTTOU信号
+                posix_kill($pid, SIGTTOU);
+            }
+            // 设置标记
+            self::$terminalClosed = true;
+        }
+    }
+    
+    /**
      * notice,记录到日志
      * @param string $msg
      * @param bool $display
@@ -976,7 +1062,7 @@ class Master
      */
     public static function notice($msg, $display = false)
     {
-        Lib\Log::add("Server:".trim($msg));
+        Log::add("Server:".trim($msg));
         if($display)
         {
             if(self::$serviceStatus == self::STATUS_STARTING && @posix_ttyname(STDOUT))

+ 139 - 69
workerman/Core/SocketWorker.php

@@ -1,10 +1,9 @@
 <?php
 namespace Man\Core;
-use Man\Core\Events\BaseEvent;
 
-require_once WORKERMAN_ROOT_DIR . 'Core/Events/Select.php';
-require_once WORKERMAN_ROOT_DIR . 'Core/AbstractWorker.php';
-require_once WORKERMAN_ROOT_DIR . 'Core/Lib/Config.php';
+use \Man\Core\Events\BaseEvent;
+use \Man\Core\Lib\Task;
+use \Man\Core\Lib\Config;
 
 /**
  * SocketWorker 监听某个端口,对外提供网络服务的worker
@@ -120,10 +119,16 @@ abstract class SocketWorker extends AbstractWorker
     protected $prereadLength = 4;
     
     /**
-     * 该进程使用的php文件
+     * 哪些文件不监控
      * @var array
      */
-    protected $includeFiles = array();
+    protected $monitorExcludePaths = array();
+    
+    /**
+     * 哪些文件在监控中
+     * @var array
+     */
+    protected $filesToMonitor = array();
     
     /**
      * 统计信息
@@ -169,13 +174,13 @@ abstract class SocketWorker extends AbstractWorker
         $this->workerName = $worker_name ? $worker_name : get_class($this);
         
         // 是否开启长连接
-        $this->isPersistentConnection = (bool)Lib\Config::get( $this->workerName . '.persistent_connection');
+        $this->isPersistentConnection = (bool)Config::get( $this->workerName . '.persistent_connection');
         // 最大请求数,超过这个数则安全重启,如果没有配置则使用PHP_INT_MAX
-        $this->maxRequests = (int)Lib\Config::get( $this->workerName . '.max_requests');
+        $this->maxRequests = (int)Config::get( $this->workerName . '.max_requests');
         $this->maxRequests = $this->maxRequests <= 0 ? PHP_INT_MAX : $this->maxRequests;
 
         // 预读数据长度,长连接需要设置此项
-        $preread_length = (int)Lib\Config::get( $this->workerName . '.preread_length');
+        $preread_length = (int)Config::get( $this->workerName . '.preread_length');
         if($preread_length > 0)
         {
             $this->prereadLength = $preread_length;
@@ -186,13 +191,13 @@ abstract class SocketWorker extends AbstractWorker
         }
         
         // 接收缓冲区大小限制
-        if(($max_recv_buffer_size = Lib\Config::get($this->workerName . '.max_recv_buffer_size')) && $max_recv_buffer_size > 0)
+        if(($max_recv_buffer_size = Config::get($this->workerName . '.max_recv_buffer_size')) && $max_recv_buffer_size > 0)
         {
             $this->maxRecvBufferSize = $max_recv_buffer_size;
         }
         
         // 发送缓冲区大小限制
-        if(($max_send_buffer_size = Lib\Config::get($this->workerName . '.max_send_buffer_size')) && $max_send_buffer_size > 0)
+        if(($max_send_buffer_size = Config::get($this->workerName . '.max_send_buffer_size')) && $max_send_buffer_size > 0)
         {
             $this->maxSendBufferSize = $max_send_buffer_size;
         }
@@ -213,7 +218,16 @@ abstract class SocketWorker extends AbstractWorker
         $this->event = new $this->eventLoopName();
         
         // 初始化任务系统
-        \Man\Core\Lib\Task::init($this->event);
+        Task::init($this->event);
+        
+        // 哪些目录或者文件不被监控
+        if(Config::get('workerman.debug') && !Config::get($this->workerName . '.no_debug')  && !Config::get($this->workerName . '.no_reload'))
+        {
+            // 保存排除监控的目录或者文件
+            $this->monitorExcludePaths = $this->getExcludePaths();
+            // 添加任务
+            Task::add(1, array($this, 'checkFilesModify'));
+        }
     }
     
     
@@ -236,12 +250,12 @@ abstract class SocketWorker extends AbstractWorker
             if($this->protocol == 'udp')
             {
                 // 添加读udp事件
-                $this->event->add($this->mainSocket,  Events\BaseEvent::EV_READ, array($this, 'recvUdp'));
+                $this->event->add($this->mainSocket,  BaseEvent::EV_READ, array($this, 'recvUdp'));
             }
             else
             {
                 // 添加accept事件
-                $ret = $this->event->add($this->mainSocket,  Events\BaseEvent::EV_READ, array($this, 'accept'));
+                $ret = $this->event->add($this->mainSocket,  BaseEvent::EV_READ, array($this, 'accept'));
             }
         }
         
@@ -255,10 +269,17 @@ abstract class SocketWorker extends AbstractWorker
      * 停止服务
      * @return void
      */
-    public function stop()
+    public function stop($force = false)
     {
         // 触发该worker进程onStop事件
         $this->onStop();
+        
+        // 强制退出
+        if($force)
+        {
+            $this->workerStatus = self::STATUS_SHUTDOWN;
+            exit(0);
+        }
        
         // 标记这个worker开始停止服务
         if($this->workerStatus != self::STATUS_SHUTDOWN)
@@ -266,7 +287,7 @@ abstract class SocketWorker extends AbstractWorker
             // 停止接收连接
             if($this->mainSocket)
             {
-                $this->event->del($this->mainSocket, Events\BaseEvent::EV_READ);
+                $this->event->del($this->mainSocket, BaseEvent::EV_READ);
                 fclose($this->mainSocket);
             }
             $this->workerStatus = self::STATUS_SHUTDOWN;
@@ -277,6 +298,11 @@ abstract class SocketWorker extends AbstractWorker
         {
             exit(0);
         }
+        
+        // EXIT_WAIT_TIME秒后退出进程
+        Task::add(self::EXIT_WAIT_TIME, function(){
+            exit(0);
+        });
     }
     
     /**
@@ -292,7 +318,7 @@ abstract class SocketWorker extends AbstractWorker
         stream_set_blocking($this->mainSocket, 0);
         // 获取协议
         $mata_data = stream_get_meta_data($socket);
-        $this->protocol = substr($mata_data['stream_type'], 0, 3);
+        list($this->protocol) = explode('_' ,$mata_data['stream_type']);
     }
     
     /**
@@ -303,7 +329,6 @@ abstract class SocketWorker extends AbstractWorker
     public function setEventLoopName($event_loop_name)
     {
         $this->eventLoopName = "\\Man\\Core\\Events\\".$event_loop_name;
-        require_once WORKERMAN_ROOT_DIR . 'Core/Events/'.ucfirst(str_replace('WORKERMAN', '', $event_loop_name)).'.php';
     }
     
     /**
@@ -331,7 +356,7 @@ abstract class SocketWorker extends AbstractWorker
         
         // 非阻塞
         stream_set_blocking($this->connections[$fd], 0);
-        $this->event->add($this->connections[$fd], Events\BaseEvent::EV_READ , array($this, 'dealInputBase'), $fd);
+        $this->event->add($this->connections[$fd], BaseEvent::EV_READ , array($this, 'dealInputBase'), $fd);
         return $new_connection;
     }
     
@@ -465,8 +490,6 @@ abstract class SocketWorker extends AbstractWorker
         {
             // 停止服务
             $this->stop();
-            // EXIT_WAIT_TIME秒后退出进程
-            pcntl_alarm(self::EXIT_WAIT_TIME);
         }
     }
     
@@ -484,8 +507,8 @@ abstract class SocketWorker extends AbstractWorker
         // udp忽略
         if($this->protocol != 'udp' && isset($this->connections[$fd]))
         {
-            $this->event->del($this->connections[$fd], Events\BaseEvent::EV_READ);
-            $this->event->del($this->connections[$fd], Events\BaseEvent::EV_WRITE);
+            $this->event->del($this->connections[$fd], BaseEvent::EV_READ);
+            $this->event->del($this->connections[$fd], BaseEvent::EV_WRITE);
             fclose($this->connections[$fd]);
         }
         unset($this->connections[$fd], $this->recvBuffers[$fd], $this->sendBuffers[$fd]);
@@ -497,18 +520,16 @@ abstract class SocketWorker extends AbstractWorker
      */
     protected function installSignal()
     {
-        // 闹钟信号
-        $this->event->add(SIGALRM, Events\BaseEvent::EV_SIGNAL, array($this, 'signalHandler'));
         // 终止进程信号
-        $this->event->add(SIGINT, Events\BaseEvent::EV_SIGNAL, array($this, 'signalHandler'));
+        $this->event->add(SIGINT, BaseEvent::EV_SIGNAL, array($this, 'signalHandler'));
         // 平滑重启信号
-        $this->event->add(SIGHUP, Events\BaseEvent::EV_SIGNAL, array($this, 'signalHandler'));
+        $this->event->add(SIGHUP, BaseEvent::EV_SIGNAL, array($this, 'signalHandler'));
         // 报告进程状态
-        $this->event->add(SIGUSR1, Events\BaseEvent::EV_SIGNAL, array($this, 'signalHandler'));
+        $this->event->add(SIGUSR1, BaseEvent::EV_SIGNAL, array($this, 'signalHandler'));
         // 报告该进程使用的文件
-        $this->event->add(SIGUSR2, Events\BaseEvent::EV_SIGNAL, array($this, 'signalHandler'));
+        $this->event->add(SIGUSR2, BaseEvent::EV_SIGNAL, array($this, 'signalHandler'));
         // 关闭标准输入输出
-        $this->event->add(SIGTTOU, Events\BaseEvent::EV_SIGNAL, array($this, 'signalHandler'));
+        $this->event->add(SIGTTOU, BaseEvent::EV_SIGNAL, array($this, 'signalHandler'));
         
         // 设置忽略信号
         pcntl_signal(SIGTTIN, SIG_IGN);
@@ -526,39 +547,26 @@ abstract class SocketWorker extends AbstractWorker
     {
         switch($signal)
         {
-            // 时钟处理函数
-            case SIGALRM:
-                // 停止服务后EXIT_WAIT_TIME秒还没退出则强制退出
-                if($this->workerStatus == self::STATUS_SHUTDOWN)
-                {
-                    exit(0);
-                }
-                break;
             // 停止该进程
             case SIGINT:
                 $this->stop();
-                // EXIT_WAIT_TIME秒后退出进程
-                pcntl_alarm(self::EXIT_WAIT_TIME);
                 break;
             // 平滑重启
             case SIGHUP:
                 $this->onReload();
                 // 如果配置了no_reload则不重启该进程
-                if(\Man\Core\Lib\Config::get($this->workerName.'.no_reload'))
+                if(Config::get($this->workerName.'.no_reload'))
                 {
                     return;
                 }
                 $this->stop();
-                // EXIT_WAIT_TIME秒后退出进程
-                pcntl_alarm(self::EXIT_WAIT_TIME);
                 break;
             // 报告进程状态
             case SIGUSR1:
                 $this->writeStatusToQueue();
                 break;
-            // 报告进程使用的php文件
+            // 预留空
             case SIGUSR2:
-                $this->writeFilesListToQueue();
                 break;
             // FileMonitor检测到终端已经关闭,向此进程发送SIGTTOU信号,关闭此进程的标准输入输出
             case SIGTTOU:
@@ -617,7 +625,7 @@ abstract class SocketWorker extends AbstractWorker
             {
                 return false;
             }
-            $this->event->add($this->connections[$this->currentDealFd],  Events\BaseEvent::EV_WRITE, array($this, 'tcpWriteToClient'));
+            $this->event->add($this->connections[$this->currentDealFd],  BaseEvent::EV_WRITE, array($this, 'tcpWriteToClient'));
             return null;
         }
         // udp 直接发送,要求数据包不能超过65515
@@ -663,6 +671,11 @@ abstract class SocketWorker extends AbstractWorker
      */
     public function getRemoteAddress($fd = null)
     {
+        if($this->protocol === 'unix')
+        {
+            return '';
+        }
+        
         if(empty($fd) && $this->protocol !== 'udp')
         {
             if(!isset($this->connections[$this->currentDealFd]))
@@ -689,6 +702,10 @@ abstract class SocketWorker extends AbstractWorker
      */
     public function getRemoteIp($fd = null)
     {
+        if($this->protocol === 'unix')
+        {
+            return '';
+        }
         $ip = '';
         $address= $this->getRemoteAddress($fd);
         if($address)
@@ -705,6 +722,10 @@ abstract class SocketWorker extends AbstractWorker
      */
     public function getRemotePort($fd = null)
     {
+        if($this->protocol === 'unix')
+        {
+            return 0;
+        }
         $port = 0;
         $address= $this->getRemoteAddress($fd);
         if($address)
@@ -759,29 +780,6 @@ abstract class SocketWorker extends AbstractWorker
     }
     
     /**
-     * 开发环境将当前进程使用的文件写入消息队列,用于FileMonitor监控文件更新
-     * @return void
-     */
-    protected function writeFilesListToQueue()
-    {
-        if(!Master::getQueueId())
-        {
-            return;
-        }
-        $error_code = 0;
-        $flip_file_list = array_flip(get_included_files());
-        $file_list = array_diff_key($flip_file_list, $this->includeFiles);
-        $this->includeFiles = $flip_file_list;
-        if($file_list)
-        {
-            foreach(array_chunk($file_list, 10, true) as $list)
-            {
-                @msg_send(Master::getQueueId(), self::MSG_TYPE_FILE_MONITOR, array_keys($list), true, false, $error_code);
-            }
-        }
-    }
-    
-    /**
      * 是否所有任务都已经完成
      * @return bool
      */
@@ -816,6 +814,78 @@ abstract class SocketWorker extends AbstractWorker
         return empty($this->connections);
     }
     
+    /**
+     * 检查文件更新时间,如果有更改则平滑重启服务(开发的时候用到)
+     * @return void
+     */
+    public function checkFilesModify()
+    {
+        // 当前进程使用的所有php文件
+        $include_files = get_included_files();
+        // 清除文件缓存
+        clearstatcache();
+        foreach($include_files as $file)
+        {
+            // 是新文件,尝试加入监控列表
+            if(!isset($this->filesToMonitor[$file]))
+            {
+                $is_exclude_file = false;
+                foreach($this->monitorExcludePaths as $path)
+                {
+                    // 是被排除的文件
+                    if(0  === strpos($file, $path))
+                    {
+                        $is_exclude_file = true;
+                        break;
+                    }
+                }
+                // 不是排除文件则加入监控列表
+                if(!$is_exclude_file)
+                {
+                    if($mtime = @filemtime($file))
+                    {
+                        $this->filesToMonitor[$file] = $mtime;
+                    }
+                }
+                continue;
+            }
+            
+            // 是已经加入监控列表的文件,查看文件更改时间
+            $mtime_now = @filemtime($file);
+            if(false === $mtime_now)
+            {
+                unset($this->filesToMonitor[$file]);
+                continue;
+            }
+            // 文件有修改,退出进程以便重新加载文件
+            if($this->filesToMonitor[$file] != $mtime_now)
+            {
+                $this->notice("$file updated and reload workers");
+                $this->stop(true);
+            }
+        }
+    }
+    
+    /**
+     * 那些路径不监控更新
+     * @return array
+     */
+    protected function getExcludePaths()
+    {
+        $config_exclude_path = Config::get('Monitor.exclude_path');
+        // 被排除的路径
+        $exclude_path = array();
+        // 因为配置可能会被更改,所以每次都会重新从配置中查找排除路径
+        foreach($config_exclude_path as $path)
+        {
+            if($real_path = realpath($path))
+            {
+                $exclude_path[] = $real_path;
+            }
+        }
+        return (array)$exclude_path;
+    }
+    
     
     /**
      * 该worker进程开始服务的时候会触发一次,可以在这里做一些全局的事情

+ 19 - 8
workerman/bin/workermand

@@ -5,7 +5,7 @@ ini_set('display_errors', 'on');
 ini_set('limit_memory','512M');
 ini_set('opcache.enable', false);
 date_default_timezone_set('Asia/Shanghai');
- 
+
 if(empty($argv[1]))
 {
     echo "Usage: workermand {start|stop|restart|reload|kill|status}".PHP_EOL;
@@ -31,19 +31,15 @@ if (version_compare(PHP_VERSION,'5.3.0','<'))
 require_once WORKERMAN_ROOT_DIR . 'Core/Master.php';
 
 // ==pid-file==
-require_once WORKERMAN_ROOT_DIR . 'Core/Lib/Config.php';
 Man\Core\Lib\Config::instance();
 if(!($pid_file = Man\Core\Lib\Config::get('workerman.pid_file')))
 {
-    $pid_file = '/var/run/workerman.pid';
+    $pid_file = './bin/pid';
 }
 define('WORKERMAN_PID_FILE', $pid_file);
 
 // ==log-dir==
-if(!($log_dir = Man\Core\Lib\Config::get('workerman.log_dir')))
-{
-    $log_dir = WORKERMAN_ROOT_DIR . 'logs/';
-}
+$log_dir = Man\Core\Lib\Config::get('workerman.log_dir');
 define('WORKERMAN_LOG_DIR', $log_dir . '/');
 
 // ==ipc-key==
@@ -98,6 +94,7 @@ if($cmd != 'status' && is_file(WORKERMAN_PID_FILE))
 switch($cmd)
 {
     case 'start':
+        remove_monitor_sock_file();
         Man\Core\Master::run();
         break;
     case 'stop':
@@ -110,6 +107,7 @@ switch($cmd)
         break;
     case 'restart':
         stop_and_wait();
+        remove_monitor_sock_file();
         Man\Core\Master::run();
         break;
     case 'reload':
@@ -159,6 +157,7 @@ switch($cmd)
 
 function force_kill()
 {
+    remove_monitor_sock_file();
     $ret = $match = array();
     exec("ps aux | grep -E '".Man\Core\Master::NAME.":|workermand' | grep -v grep", $ret);
     $this_pid = posix_getpid();
@@ -178,6 +177,7 @@ function force_kill()
 
 function stop_and_wait($wait_time = 6)
 {
+    remove_monitor_sock_file();
     $pid = @file_get_contents(WORKERMAN_PID_FILE);
     if(empty($pid))
     {
@@ -204,4 +204,15 @@ function stop_and_wait($wait_time = 6)
     }
 }
 
-
+function remove_monitor_sock_file()
+{
+    $monitor_listen = \Man\Core\Lib\Config::get('Monitor.listen');
+    if(strpos($monitor_listen, 'unix') === 0)
+    {
+        $sock_file =  str_replace('unix://', '', $monitor_listen);
+        if(is_writeable($sock_file))
+        {
+            unlink($sock_file);
+        }
+    }
+}

+ 0 - 13
workerman/conf/conf.d/FileMonitor.conf

@@ -1,13 +0,0 @@
-;监控workerman所使用文件的更新,如果文件有更新,并且conf/Workerman.conf中debug=1则自动运行reload,即平滑重启所有进程以便重新加载修改的php文件到内存
-;worker_file
-worker_file = Common/FileMonitor.php
-;此worker进程不监听端口,主要用来监控文件更新,需要root权限
-;listen=
-;启动多少worker进程
-start_workers=1
-;以哪个用户运行该worker进程,需要root权限
-user=root
-;排除文件或者目录,这些文件或者目录下的文件将不会被监控,可以是相对路径或者绝对路径
-exclude_path[]=./logs/
-exclude_path[]=/tmp/
-exclude_path[]=/path/example.php

+ 0 - 25
workerman/conf/conf.d/Monitor.conf

@@ -1,25 +0,0 @@
-;==该worker的说明==
-;①监听2009端口,并提供telnet远程控制功能
-;②监控worker进程退出次数及状态,有异常时告警(告警发送邮件或者短信需要自己实现)
-;③监控master进程是否异常退出
-;④监控每个worker进程内存是否大于设定值,大于设定值则安全重启对应进程
-;worker_file
-worker_file = Common/Monitor.php
-;监听ip及端口,不使用的情况为了安全请绑定到127.0.0.1只限本机访问,如果绑定0.0.0.0,则记得更改下面telnet密码配置
-listen = tcp://127.0.0.1:2009
-;telnet需要长连接
-persistent_connection = 1
-;启动多少进程,1个就够
-start_workers=1
-;以哪个用户运行这个worker进程,需要root权限
-user=root
-;预读长度
-preread_length=64
-
-;==以下是自定义的配置==
-;如果worker进程1分钟内退出max_worker_exit_count次则触发告警
-max_worker_exit_count=2000
-;worker进程最大内存阈值(单位KByte),超过这个值安全重启(reload)这个进程
-max_mem_limit=124000
-;telnet密码
-password=yourpassword

+ 10 - 6
workerman/conf/workerman.conf

@@ -1,10 +1,14 @@
-;debug=1则var_dump、echo、php notcie等会在终端上打印出来
+;debug=1则var_dump、echo、php notcie等会在终端上打印出来,并且会监控文件更新
+;开发环境可以设置为1,线上环境请设置成0
 debug=1
-;保存主进程pid的文件
-pid_file=/var/run/workerman.pid
+
 ;日志文件目录
 log_dir=./logs/
-;backlog设置
-backlog=1024
+
 ;应用配置
-include=/conf.d/*.conf
+include=../applications/*/conf.d/*.conf
+
+[Monitor]
+;排除监控文件或者目录,这些文件或者目录下的文件将不会被监控和自动更新,可以是相对路径或者绝对路径
+exclude_path[]=/tmp/
+exclude_path[]=/path/example.php