'healthy', 'checks' => [] ]; // --- 数据库连接检查 (修改为适应Typecho现代化配置) --- function checkDatabaseConnection() { // 假设 Typecho 的配置文件是 config.inc.php $configFilePath = __DIR__ . '/config.inc.php'; if (!file_exists($configFilePath)) { return ['status' => 'critical', 'message' => 'Typecho configuration file (config.inc.php) not found.']; } // 尝试包含 config.inc.php 文件 // 这将初始化 Typecho 的数据库连接对象 try { require_once $configFilePath; // 检查 Typecho 的 Db 类是否已初始化并可用 if (!class_exists('\Typecho\Db') || !\Typecho\Db::get()) { return ['status' => 'critical', 'message' => 'Typecho database object not initialized or failed to get instance.']; } // 获取数据库实例 $db = \Typecho\Db::get(); // 尝试执行一个简单的查询来验证连接和权限 // Typecho 的 Db 对象没有直接的 `query` 方法用于简单SQL, // 可以通过 `fetchRow` 或 `fetchObject` 来执行 select 语句 // 或者直接通过 Typecho_Db_Adapter::test() 方法 (如果存在且公开的话) // 这里我们尝试查询一个 Typecho 常用表,例如 'typecho_options' // 注意: Typecho 的 Db::query 方法返回的是结果集对象,不是直接布尔值 // 我们需要确保查询没有抛出异常,并能获取到结果。 // 修正:直接从 $db 对象获取前缀 $optionsTableName = $db->getPrefix() . 'options'; // 尝试查询一条数据,确认连接活跃且表可访问 $db->fetchRow($db->select()->from($optionsTableName)->limit(1)); return ['status' => 'healthy', 'message' => 'Database connection successful and query executed.']; } catch (\Typecho\Db\Exception $e) { return ['status' => 'critical', 'message' => 'Database connection failed: ' . $e->getMessage()]; } catch (Exception $e) { return ['status' => 'critical', 'message' => 'An unexpected error occurred during database check: ' . $e->getMessage()]; } } $status['checks']['database'] = checkDatabaseConnection(); if ($status['checks']['database']['status'] === 'critical') { $status['overall'] = 'unhealthy'; } // --- 文件系统权限检查 --- function checkFilePermissions() { $paths = [ 'usr/uploads' => 'write', // 用户上传目录 'config.inc.php' => 'read', // 配置文件 'var/Widget/Contents/Post/Edit.php' => 'read' // 核心文件示例 ]; $results = []; foreach ($paths as $path => $permissionType) { $fullPath = __DIR__ . DIRECTORY_SEPARATOR . $path; if (!file_exists($fullPath)) { $results[$path] = ['status' => 'warning', 'message' => "Path not found: {$path}"]; continue; } $canAccess = false; if ($permissionType === 'read') { $canAccess = is_readable($fullPath); } elseif ($permissionType === 'write') { // 对于目录,检查是否可写入 if (is_dir($fullPath)) { $testFile = $fullPath . DIRECTORY_SEPARATOR . uniqid('health_check_') . '.tmp'; if (file_put_contents($testFile, 'test') !== false) { unlink($testFile); // 删除测试文件 $canAccess = true; } } else { $canAccess = is_writable($fullPath); } } if ($canAccess) { $results[$path] = ['status' => 'healthy', 'message' => "{$permissionType} access OK."]; } else { $results[$path] = ['status' => 'critical', 'message' => "{$permissionType} access FAILED."]; } } return $results; } $status['checks']['file_permissions'] = checkFilePermissions(); foreach ($status['checks']['file_permissions'] as $pathStatus) { if ($pathStatus['status'] === 'critical') { $status['overall'] = 'unhealthy'; break; } } // --- 核心文件可访问性检查 (HTTP请求) --- // 注意:这个检查需要服务器环境支持CURL或file_get_contents对外部URL的访问 // 并且检查的是Web服务器是否能正常提供这些文件,而不是PHP脚本本身是否能访问 function checkCoreFileAccess() { $baseUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://{$_SERVER['HTTP_HOST']}"; // 假设这些文件是可以通过HTTP访问的Typecho核心文件 // 这里需要根据你的Typecho安装路径和实际可访问的文件来调整 $coreFiles = [ '/index.php', // 首页 '/admin/index.php' // 后台登录页 ]; $results = []; foreach ($coreFiles as $file) { $url = $baseUrl . $file; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 5); // 5秒超时 curl_setopt($ch, CURLOPT_NOBODY, true); // 只获取头部信息,不下载内容 curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode >= 200 && $httpCode < 400) { $results[$file] = ['status' => 'healthy', 'message' => "Accessible (HTTP {$httpCode})."]; } else { $results[$file] = ['status' => 'critical', 'message' => "Not accessible (HTTP {$httpCode})."]; } } return $results; } // 仅在服务器支持CURL的情况下执行此检查 if (function_exists('curl_init')) { $status['checks']['core_file_access'] = checkCoreFileAccess(); foreach ($status['checks']['core_file_access'] as $fileStatus) { if ($fileStatus['status'] === 'critical') { $status['overall'] = 'unhealthy'; break; } } } else { $status['checks']['core_file_access'] = ['status' => 'warning', 'message' => 'cURL extension is not enabled, skipping core file HTTP access check.']; } // 输出 JSON 结果 echo json_encode($status, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); ?>