代码优化

This commit is contained in:
wong
2026-01-19 10:30:09 +08:00
parent 16aec83f02
commit 6b31889261
2 changed files with 176 additions and 14 deletions

View File

@@ -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 '未知错误';
}
}
/** /**
* 清理僵尸进程 * 清理僵尸进程
*/ */

View File

@@ -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) {