* @version 2.0 - 2011-11-25 * @package Daemon */ include_once(dirname(dirname(dirname(__FILE__)))."/library/publicBase.php"); date_default_timezone_set("Asia/Shanghai"); abstract class cronBase { protected $process; // 队列进程列表,必选项 protected $procnumlist; // 队列进程数限制,必选项 protected $procnum = 0; // 默认启动进程数 protected $maxtimelist; // 队列进程最大执行时间限制列表 protected $maxtime = 480; // 队列一次循环的默认最长时间, 未自定义则该项有效, 超过该值进程将被杀死 protected $bin_php = '/usr/local/bin/php'; // php执行文件路径 private $path_daemon; // ROOT根目录 private $proc_start; // 启动队列的进程信息 private $path_prochealth; // 进程健康路径 private $path_conf; // 配置文件路径 public function __construct() { $this->path_conf = dirname(dirname(__FILE__))."/config/daemonconf.php"; include_once($this->path_conf); $this->path_daemon = dirname(dirname(dirname(__FILE__))).'/queue/deal/'; $this->path_prochealth = dirname(dirname(dirname(__FILE__))).'/queue/cache/proc/deal_%s.txt'; $this->setPara(); $this->prepare(); $this->checkProc(); $this->startProc(); return true; } /* 子类必须实现,设置队列运行所须属性 */ public abstract function setPara(); private function prepare() { $dir_prochealth = dirname($this->path_prochealth); if(!is_dir($dir_prochealth)) system("mkdir -p $dir_prochealth"); if(empty($this->process)) exit("No dealscript.\n"); } private function checkProc() { $obj = new mBase(); $server_ip = $obj->getServerIp(); $rdobj = $obj->initRedis(); // 检测 foreach($this->process as $deal_flag => $proc) { $active_proc_codes = array(); // 搜集存活的进程号、数 $path_proc = $this->path_daemon.$proc; $chk_shell = "ps -ef|grep '{$path_proc}'|grep -v grep|grep -v '\/bin\/sh'|awk -F ' ' '{print $2\" \"$10\" \"$11}'"; $maxtime = $this->maxtimelist[$deal_flag]+0>0 ? $this->maxtimelist[$deal_flag] : $this->maxtime; $fp = @popen($chk_shell, 'r'); while (!feof($fp)) { $buffer = fgets($fp, 4096); $procinfo = explode(' ', trim($buffer)); $procid = $procinfo[0]+0; $proc_code = is_numeric($procinfo[2]) ? $procinfo[2] : $procinfo[1]+0; if($procid==0) continue; // 杀死僵死进程 $lasttime = $rdobj->get(sprintf(_DAEMON_HEALTH, $server_ip, $deal_flag, $proc_code)); if($lasttime === false || time()-$lasttime > $maxtime) { system("/bin/kill -9 $procid"); error_log('['.date('Y-m-d H:i:s').']kill:'.$path_proc.'|'.$proc_code.'_'.md5($path_proc).'|'.time().'|'.$lasttime.'|'.$maxtime."\n", 3, dirname(dirname(__FILE__)).'/cache/proc/cron_track.log'); } else { // 存活的进程 $active_proc_codes[] = $proc_code; } } $procnum = $this->procnumlist[$deal_flag]+0>0 ? $this->procnumlist[$deal_flag] : $this->procnum; for($i=0;$i<$procnum;$i++) { if(in_array($i, $active_proc_codes)) continue; $this->proc_start[$deal_flag]['proc'] = $path_proc; $this->proc_start[$deal_flag]['startnum'][] = $i; } if($fp) @pclose($fp); } } /* 检查进程运行情况检测, 杀僵死进程, 启动进程 */ private function startProc() { // 启动队列 if(empty($this->proc_start)) return ; foreach($this->proc_start as $deal_flag => $proc) { if(empty($proc['startnum'])) continue; foreach ($proc['startnum'] as $proc_code) { $cmd = "{$this->bin_php} {$proc['proc']} {$deal_flag} {$proc_code} &"; //echo $cmd."\n"; //error_log('['.date('Y-m-d H:i:s').']startproc:'.$cmd."\n", 3, dirname(__FILE__).'/cron_track.log'); $fp = @popen($cmd, "r"); if($fp) @pclose($fp); } } } }