/** * [runTask 运行任务] * @param [type] $taskId [description] * @param [type] $ipList [description] * @param [type] $cmd [description] * @param [type] $timeout [description] * @return [array] [ip:ok, failed, overtime] */ public function runTask($taskId, $ipList, $cmd, $timeout = null) { $this->logger->info("START RUN TASK:{$taskId}"); if (empty($timeout)) { $timeout = $this->timeout; } //执行命令 $shellCmd = 'mkdir -p /tmp/pkg_tools_v3/;' . 'rsync -a #rsyncd_svr#::pkg_home/pkg_tools/ /tmp/pkg_tools_v3/;' . 'cd /tmp/pkg_tools_v3/;' . "{$cmd};" . 'cd scan_pkg;' . './scan_packages_info.sh >/dev/null 2>&1 & '; $this->logger->info("command:{$shellCmd}"); $shellRun = new ShellExec(); $taskList = $shellRun->runCmd($shellCmd, $ipList); $this->logger->info('TASK LIST:' . json_encode($taskList)); //初始化任务状态 已启动 foreach ($taskList as $shellTaskId => $taskInfo) { foreach ($taskInfo['ip_status'] as $ip => $info) { $status = 'started'; $msg = 'task type:' . $taskInfo['type'] . ';' . 'shell taskid:' . $shellTaskId; $this->logger->info("ip:{$ip}, msg:{$msg}, status:{$status}"); $this->updateStatus($ip, $taskId, $status, $msg, $msg); } } $startTime = time(); $ipStatus = array(); $done = array(); $overtime = false; while (true) { $useTime = time() - $startTime; if ($useTime >= $timeout) { $overtime = true; break; } //获取任务执行情况 $taskList = $shellRun->getTaskInfo($taskList); $this->logger->info("taskList info" . json_encode($taskList)); $finished = true; foreach ($taskList as $shellTaskId => $taskInfo) { if ($taskInfo['status'] != 'ok') { $finished = false; } foreach ($taskInfo['ip_status'] as $ip => $info) { if (array_key_exists($ip, $done) && $done[$ip] == true) { continue; } if (strpos($info['status'], 'fail') !== false) { //失败的 $done[$ip] = true; $status = 'failed'; $msg = $info['msg']; $this->logger->info("ip:{$ip}, taskid:{$taskId}, status:{$status}, msg:{$msg}"); $this->updateStatus($ip, $taskId, $status, $msg, $msg); } elseif ($info['status'] == 'ok') { //成功的则获取命令输出并更新到数据库 $done[$ip] = true; //匹配成功的输出 两种:result 或 resultLine $matchCount = preg_match_all('/result%%(\\w+)%%(.*)%%/', $info['msg'], $matches); if ($matchCount > 0) { $result = end($matches[1]); $msg = end($matches[2]); } if ($result == 'success') { $status = 'ok'; } else { $status = 'failed'; } $matchCount = preg_match_all('/%%resultLine%%([^%]*)%%([^%]*)%%([^%]*)%%([^%]*)%%([^%]*)%%([^%]*)%%([^%]*)%%/', $info['msg'], $matches); if ($matchCount > 0) { $result = end($matches[6]); $start = end($matches[7]); if ($result == 'success') { if (empty($start)) { $status = 'ok'; } else { $status = 'failed'; $msg = $start; } } else { $status = 'failed'; } } $this->logger->info("ip:{$ip}, taskid:{$taskId}, status:{$status}, msg:{$msg}"); $this->updateStatus($ip, $taskId, $status, $msg, $info['msg']); } } } if ($finished == true) { break; } sleep(3); } $this->logger->info('task list:' . json_encode($taskList)); $resultArray = array(); //因为超时退出时, 将未结束的ip设置为fail if ($overtime == true) { $this->logger->info('overtime, set undone ip failed'); foreach ($ipList as $ip) { $toSelect = array('task_id' => $taskId, 'ip' => $ip); $dbRes = $this->database->selectValue($toSelect, Conf::get('mysqlTaskResultTableName')); $status = 'ok'; foreach ($dbRes as $index => $ipTaskInfo) { if ($ipTaskInfo['status'] != 'ok' && $ipTaskInfo['status'] != 'failed') { $ip = $ipTaskInfo['ip']; $status = 'failed'; $msg = 'shell run timeout'; $resultArray[$ip] = 'overtime'; $this->logger->info("ip:{$ip}, taskid:{$taskId}, status:{$status}, msg:{$msg}"); $this->updateStatus($ip, $taskId, $status, $msg, $msg); } else { $resultArray[$ip] = $ipTaskInfo['status']; } } } } $this->updateTaskStatus($taskId); return $resultArray; }