代码优化
This commit is contained in:
@@ -432,6 +432,10 @@ class TaskSchedulerCommand extends Command
|
|||||||
$logMessage .= "执行时间: " . date('Y-m-d H:i:s') . "\n";
|
$logMessage .= "执行时间: " . date('Y-m-d H:i:s') . "\n";
|
||||||
$logMessage .= "执行目录: {$executionPath}\n";
|
$logMessage .= "执行目录: {$executionPath}\n";
|
||||||
$logMessage .= "命令: {$command}\n";
|
$logMessage .= "命令: {$command}\n";
|
||||||
|
$logMessage .= "[DEBUG] 任务配置: " . json_encode($task, JSON_UNESCAPED_UNICODE) . "\n";
|
||||||
|
$logMessage .= "[DEBUG] 当前工作目录: " . getcwd() . "\n";
|
||||||
|
$logMessage .= "[DEBUG] PHP版本: " . PHP_VERSION . "\n";
|
||||||
|
$logMessage .= "[DEBUG] 操作系统: " . PHP_OS . "\n";
|
||||||
$logMessage .= str_repeat('=', 60) . "\n";
|
$logMessage .= str_repeat('=', 60) . "\n";
|
||||||
file_put_contents($logFile, $logMessage, FILE_APPEND);
|
file_put_contents($logFile, $logMessage, FILE_APPEND);
|
||||||
|
|
||||||
@@ -445,16 +449,30 @@ class TaskSchedulerCommand extends Command
|
|||||||
2 => ['pipe', 'w'], // stderr
|
2 => ['pipe', 'w'], // stderr
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// [DEBUG] 记录进程启动前信息
|
||||||
|
$debugLog = "[DEBUG] 准备启动进程\n";
|
||||||
|
$debugLog .= "[DEBUG] PHP路径: {$phpPath}\n";
|
||||||
|
$debugLog .= "[DEBUG] Think路径: {$thinkPath}\n";
|
||||||
|
$debugLog .= "[DEBUG] 执行目录: {$executionPath}\n";
|
||||||
|
$debugLog .= "[DEBUG] 完整命令: {$command}\n";
|
||||||
|
$debugLog .= "[DEBUG] 超时设置: {$timeout}秒\n";
|
||||||
|
file_put_contents($logFile, $debugLog, FILE_APPEND);
|
||||||
|
|
||||||
$process = @proc_open($command, $descriptorspec, $pipes, $executionPath);
|
$process = @proc_open($command, $descriptorspec, $pipes, $executionPath);
|
||||||
|
|
||||||
if (!is_resource($process)) {
|
if (!is_resource($process)) {
|
||||||
$errorMsg = "任务执行失败: 无法启动进程";
|
$errorMsg = "任务执行失败: 无法启动进程";
|
||||||
|
$errorMsg .= "\n[DEBUG] proc_open 返回: " . var_export($process, true);
|
||||||
|
$errorMsg .= "\n[DEBUG] 错误信息: " . error_get_last()['message'] ?? '无错误信息';
|
||||||
Log::error($errorMsg, ['task' => $taskId]);
|
Log::error($errorMsg, ['task' => $taskId]);
|
||||||
file_put_contents($logFile, $errorMsg . "\n", FILE_APPEND);
|
file_put_contents($logFile, $errorMsg . "\n", FILE_APPEND);
|
||||||
$this->removeLock($taskId); // 删除锁文件
|
$this->removeLock($taskId); // 删除锁文件
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [DEBUG] 记录进程启动成功
|
||||||
|
file_put_contents($logFile, "[DEBUG] 进程启动成功,进程资源类型: " . get_resource_type($process) . "\n", FILE_APPEND);
|
||||||
|
|
||||||
// 设置非阻塞模式
|
// 设置非阻塞模式
|
||||||
stream_set_blocking($pipes[1], false);
|
stream_set_blocking($pipes[1], false);
|
||||||
stream_set_blocking($pipes[2], false);
|
stream_set_blocking($pipes[2], false);
|
||||||
@@ -462,34 +480,80 @@ class TaskSchedulerCommand extends Command
|
|||||||
$startWaitTime = time();
|
$startWaitTime = time();
|
||||||
$output = '';
|
$output = '';
|
||||||
$error = '';
|
$error = '';
|
||||||
|
$loopCount = 0;
|
||||||
|
$lastStatusCheck = 0;
|
||||||
|
|
||||||
// 等待进程完成或超时
|
// 等待进程完成或超时
|
||||||
while (true) {
|
while (true) {
|
||||||
|
$loopCount++;
|
||||||
$status = proc_get_status($process);
|
$status = proc_get_status($process);
|
||||||
|
|
||||||
|
// [DEBUG] 每10次循环记录一次状态(减少日志量)
|
||||||
|
if ($loopCount % 10 == 0 || time() - $lastStatusCheck > 5) {
|
||||||
|
$elapsed = time() - $startWaitTime;
|
||||||
|
$debugStatus = "[DEBUG] 循环 #{$loopCount}, 已运行 {$elapsed}秒\n";
|
||||||
|
$debugStatus .= "[DEBUG] 进程状态: running=" . ($status['running'] ? 'true' : 'false');
|
||||||
|
if (isset($status['exitcode'])) {
|
||||||
|
$debugStatus .= ", exitcode=" . $status['exitcode'];
|
||||||
|
}
|
||||||
|
if (isset($status['signaled'])) {
|
||||||
|
$debugStatus .= ", signaled=" . ($status['signaled'] ? 'true' : 'false');
|
||||||
|
}
|
||||||
|
if (isset($status['termsig'])) {
|
||||||
|
$debugStatus .= ", termsig=" . $status['termsig'];
|
||||||
|
}
|
||||||
|
$debugStatus .= "\n";
|
||||||
|
file_put_contents($logFile, $debugStatus, FILE_APPEND);
|
||||||
|
$lastStatusCheck = time();
|
||||||
|
}
|
||||||
|
|
||||||
// 读取输出
|
// 读取输出
|
||||||
$output .= stream_get_contents($pipes[1]);
|
$outputChunk = stream_get_contents($pipes[1]);
|
||||||
$error .= stream_get_contents($pipes[2]);
|
$errorChunk = stream_get_contents($pipes[2]);
|
||||||
|
|
||||||
|
if (!empty($outputChunk)) {
|
||||||
|
$output .= $outputChunk;
|
||||||
|
file_put_contents($logFile, "[DEBUG] 标准输出片段: " . substr($outputChunk, 0, 200) . "\n", FILE_APPEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($errorChunk)) {
|
||||||
|
$error .= $errorChunk;
|
||||||
|
file_put_contents($logFile, "[DEBUG] 错误输出片段: " . substr($errorChunk, 0, 200) . "\n", FILE_APPEND);
|
||||||
|
}
|
||||||
|
|
||||||
// 检查是否完成
|
// 检查是否完成
|
||||||
if (!$status['running']) {
|
if (!$status['running']) {
|
||||||
|
// [DEBUG] 记录进程结束时的详细状态
|
||||||
|
$debugEnd = "[DEBUG] 进程已结束\n";
|
||||||
|
$debugEnd .= "[DEBUG] 最终状态: " . json_encode($status, JSON_UNESCAPED_UNICODE) . "\n";
|
||||||
|
if (isset($status['exitcode'])) {
|
||||||
|
$debugEnd .= "[DEBUG] proc_get_status 返回的退出码: " . $status['exitcode'] . "\n";
|
||||||
|
}
|
||||||
|
file_put_contents($logFile, $debugEnd, FILE_APPEND);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查超时
|
// 检查超时
|
||||||
if ((time() - $startWaitTime) > $timeout) {
|
if ((time() - $startWaitTime) > $timeout) {
|
||||||
|
$timeoutMsg = "任务执行超时({$timeout}秒),终止进程\n";
|
||||||
|
$timeoutMsg .= "[DEBUG] 当前循环次数: {$loopCount}\n";
|
||||||
|
$timeoutMsg .= "[DEBUG] 已运行时间: " . (time() - $startWaitTime) . "秒\n";
|
||||||
Log::warning("任务执行超时({$timeout}秒),终止进程", ['task' => $taskId]);
|
Log::warning("任务执行超时({$timeout}秒),终止进程", ['task' => $taskId]);
|
||||||
file_put_contents($logFile, "任务执行超时({$timeout}秒),终止进程\n", FILE_APPEND);
|
file_put_contents($logFile, $timeoutMsg, FILE_APPEND);
|
||||||
|
|
||||||
if (function_exists('proc_terminate')) {
|
if (function_exists('proc_terminate')) {
|
||||||
proc_terminate($process);
|
$terminateResult = proc_terminate($process);
|
||||||
|
file_put_contents($logFile, "[DEBUG] proc_terminate 返回: " . var_export($terminateResult, true) . "\n", FILE_APPEND);
|
||||||
|
} else {
|
||||||
|
file_put_contents($logFile, "[DEBUG] proc_terminate 函数不可用\n", FILE_APPEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭管道
|
// 关闭管道
|
||||||
@fclose($pipes[0]);
|
@fclose($pipes[0]);
|
||||||
@fclose($pipes[1]);
|
@fclose($pipes[1]);
|
||||||
@fclose($pipes[2]);
|
@fclose($pipes[2]);
|
||||||
proc_close($process);
|
$closeResult = proc_close($process);
|
||||||
|
file_put_contents($logFile, "[DEBUG] 超时后 proc_close 返回: {$closeResult}\n", FILE_APPEND);
|
||||||
|
|
||||||
$this->removeLock($taskId); // 删除锁文件
|
$this->removeLock($taskId); // 删除锁文件
|
||||||
return;
|
return;
|
||||||
@@ -500,17 +564,43 @@ class TaskSchedulerCommand extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 读取剩余输出
|
// 读取剩余输出
|
||||||
$output .= stream_get_contents($pipes[1]);
|
$remainingOutput = stream_get_contents($pipes[1]);
|
||||||
$error .= stream_get_contents($pipes[2]);
|
$remainingError = stream_get_contents($pipes[2]);
|
||||||
|
|
||||||
|
if (!empty($remainingOutput)) {
|
||||||
|
$output .= $remainingOutput;
|
||||||
|
file_put_contents($logFile, "[DEBUG] 剩余标准输出: " . substr($remainingOutput, 0, 500) . "\n", FILE_APPEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($remainingError)) {
|
||||||
|
$error .= $remainingError;
|
||||||
|
file_put_contents($logFile, "[DEBUG] 剩余错误输出: " . substr($remainingError, 0, 500) . "\n", FILE_APPEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [DEBUG] 记录关闭管道前的状态
|
||||||
|
file_put_contents($logFile, "[DEBUG] 准备关闭管道,输出长度: " . strlen($output) . ", 错误长度: " . strlen($error) . "\n", FILE_APPEND);
|
||||||
|
|
||||||
// 关闭管道
|
// 关闭管道
|
||||||
@fclose($pipes[0]);
|
$closeResults = [];
|
||||||
@fclose($pipes[1]);
|
$closeResults['stdin'] = @fclose($pipes[0]);
|
||||||
@fclose($pipes[2]);
|
$closeResults['stdout'] = @fclose($pipes[1]);
|
||||||
|
$closeResults['stderr'] = @fclose($pipes[2]);
|
||||||
|
file_put_contents($logFile, "[DEBUG] 管道关闭结果: " . json_encode($closeResults, JSON_UNESCAPED_UNICODE) . "\n", FILE_APPEND);
|
||||||
|
|
||||||
// 获取退出码
|
// 获取退出码
|
||||||
$exitCode = proc_close($process);
|
$exitCode = proc_close($process);
|
||||||
|
|
||||||
|
// [DEBUG] 记录退出码获取结果
|
||||||
|
file_put_contents($logFile, "[DEBUG] proc_close 返回的退出码: {$exitCode}\n", FILE_APPEND);
|
||||||
|
file_put_contents($logFile, "[DEBUG] 退出码类型: " . gettype($exitCode) . "\n", FILE_APPEND);
|
||||||
|
if ($exitCode === -1) {
|
||||||
|
file_put_contents($logFile, "[DEBUG] ⚠️ 退出码为 -1,可能原因:\n", FILE_APPEND);
|
||||||
|
file_put_contents($logFile, "[DEBUG] 1. 进程被信号终止\n", FILE_APPEND);
|
||||||
|
file_put_contents($logFile, "[DEBUG] 2. 进程异常终止\n", FILE_APPEND);
|
||||||
|
file_put_contents($logFile, "[DEBUG] 3. 无法获取进程退出状态\n", FILE_APPEND);
|
||||||
|
file_put_contents($logFile, "[DEBUG] 4. Windows系统上的特殊返回值\n", FILE_APPEND);
|
||||||
|
}
|
||||||
|
|
||||||
// 记录输出
|
// 记录输出
|
||||||
if (!empty($output)) {
|
if (!empty($output)) {
|
||||||
file_put_contents($logFile, "任务输出:\n{$output}\n", FILE_APPEND);
|
file_put_contents($logFile, "任务输出:\n{$output}\n", FILE_APPEND);
|
||||||
@@ -527,12 +617,29 @@ class TaskSchedulerCommand extends Command
|
|||||||
// 获取任务名称
|
// 获取任务名称
|
||||||
$taskName = $task['name'] ?? $taskId;
|
$taskName = $task['name'] ?? $taskId;
|
||||||
|
|
||||||
|
// 解释退出码含义
|
||||||
|
$exitCodeMeaning = $this->getExitCodeMeaning($exitCode);
|
||||||
|
|
||||||
// 记录任务完成
|
// 记录任务完成
|
||||||
$logMessage = "\n" . str_repeat('=', 60) . "\n";
|
$logMessage = "\n" . str_repeat('=', 60) . "\n";
|
||||||
$logMessage .= "任务执行完成: {$taskName} ({$taskId})\n";
|
$logMessage .= "任务执行完成: {$taskName} ({$taskId})\n";
|
||||||
$logMessage .= "完成时间: " . date('Y-m-d H:i:s') . "\n";
|
$logMessage .= "完成时间: " . date('Y-m-d H:i:s') . "\n";
|
||||||
$logMessage .= "执行时长: {$duration} 秒\n";
|
$logMessage .= "执行时长: {$duration} 秒\n";
|
||||||
$logMessage .= "退出码: {$exitCode}\n";
|
$logMessage .= "退出码: {$exitCode} ({$exitCodeMeaning})\n";
|
||||||
|
$logMessage .= "[DEBUG] 输出总长度: " . strlen($output) . " 字节\n";
|
||||||
|
$logMessage .= "[DEBUG] 错误总长度: " . strlen($error) . " 字节\n";
|
||||||
|
if ($exitCode === -1) {
|
||||||
|
$logMessage .= "[DEBUG] ⚠️ 退出码 -1 详细分析:\n";
|
||||||
|
$logMessage .= "[DEBUG] - 是否有错误输出: " . (!empty($error) ? '是' : '否') . "\n";
|
||||||
|
$logMessage .= "[DEBUG] - 是否有标准输出: " . (!empty($output) ? '是' : '否') . "\n";
|
||||||
|
$logMessage .= "[DEBUG] - 执行时长: {$duration} 秒\n";
|
||||||
|
if ($duration < 1) {
|
||||||
|
$logMessage .= "[DEBUG] - ⚠️ 执行时长过短,可能是进程启动失败\n";
|
||||||
|
}
|
||||||
|
if ($duration > $timeout * 0.9) {
|
||||||
|
$logMessage .= "[DEBUG] - ⚠️ 执行时长接近超时时间\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
$logMessage .= str_repeat('=', 60) . "\n";
|
$logMessage .= str_repeat('=', 60) . "\n";
|
||||||
file_put_contents($logFile, $logMessage, FILE_APPEND);
|
file_put_contents($logFile, $logMessage, FILE_APPEND);
|
||||||
|
|
||||||
@@ -548,6 +655,7 @@ class TaskSchedulerCommand extends Command
|
|||||||
'name' => $taskName,
|
'name' => $taskName,
|
||||||
'duration' => $duration,
|
'duration' => $duration,
|
||||||
'exit_code' => $exitCode,
|
'exit_code' => $exitCode,
|
||||||
|
'exit_code_meaning' => $exitCodeMeaning,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,6 +690,50 @@ class TaskSchedulerCommand extends Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取退出码的含义说明
|
||||||
|
* @param int $exitCode 退出码
|
||||||
|
* @return string 退出码含义
|
||||||
|
*/
|
||||||
|
protected function getExitCodeMeaning($exitCode)
|
||||||
|
{
|
||||||
|
switch ($exitCode) {
|
||||||
|
case 0:
|
||||||
|
return '成功';
|
||||||
|
case -1:
|
||||||
|
return '进程被信号终止或异常终止(可能是被强制终止、超时终止或发生致命错误)';
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
case 9:
|
||||||
|
case 10:
|
||||||
|
return '一般性错误';
|
||||||
|
case 126:
|
||||||
|
return '命令不可执行';
|
||||||
|
case 127:
|
||||||
|
return '命令未找到';
|
||||||
|
case 128:
|
||||||
|
return '无效的退出参数';
|
||||||
|
case 130:
|
||||||
|
return '进程被 Ctrl+C 终止 (SIGINT)';
|
||||||
|
case 137:
|
||||||
|
return '进程被 SIGKILL 信号强制终止';
|
||||||
|
case 143:
|
||||||
|
return '进程被 SIGTERM 信号终止';
|
||||||
|
default:
|
||||||
|
if ($exitCode > 128 && $exitCode < 256) {
|
||||||
|
$signal = $exitCode - 128;
|
||||||
|
return "进程被信号 {$signal} 终止";
|
||||||
|
}
|
||||||
|
return '未知错误';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理僵尸进程
|
* 清理僵尸进程
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -80,14 +80,24 @@ class MessageChatroomListJob
|
|||||||
// 调用添加好友任务获取方法
|
// 调用添加好友任务获取方法
|
||||||
$result = $messageController->getChatroomList($pageIndex,$pageSize,true);
|
$result = $messageController->getChatroomList($pageIndex,$pageSize,true);
|
||||||
$response = json_decode($result,true);
|
$response = json_decode($result,true);
|
||||||
|
|
||||||
|
// 确保 response 是数组格式
|
||||||
|
if (!is_array($response)) {
|
||||||
|
$response = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 判断是否成功
|
// 判断是否成功
|
||||||
if ($response['code'] == 200) {
|
if (isset($response['code']) && $response['code'] == 200) {
|
||||||
$data = $response['data'];
|
$data = isset($response['data']) ? $response['data'] : [];
|
||||||
|
|
||||||
|
// 确保 data 是数组格式
|
||||||
|
if (!is_array($data)) {
|
||||||
|
$data = [];
|
||||||
|
}
|
||||||
|
|
||||||
// 判断是否有下一页,且未超过最大同步页数
|
// 判断是否有下一页,且未超过最大同步页数
|
||||||
if (!empty($data) && count($data) > 0) {
|
if (!empty($data) && is_array($data) && count($data) > 0) {
|
||||||
$nextPageIndex = $pageIndex + 1;
|
$nextPageIndex = $pageIndex + 1;
|
||||||
// 检查是否超过最大同步页数
|
// 检查是否超过最大同步页数
|
||||||
if ($nextPageIndex < self::MAX_SYNC_PAGES) {
|
if ($nextPageIndex < self::MAX_SYNC_PAGES) {
|
||||||
|
|||||||
Reference in New Issue
Block a user