PHP 自动化巡检脚本

wen PHP项目 2

本文目录导读:

PHP 自动化巡检脚本

  1. 基础巡检脚本
  2. 数据库巡检脚本
  3. 配置文件和定时任务
  4. 定时任务配置
  5. 使用说明

我来为您提供一个完整的PHP自动化巡检脚本方案,包含服务器健康检查、安全检查和性能监控等功能。

基础巡检脚本

server_check.php

<?php
/**
 * PHP服务器自动化巡检脚本
 * 用于监控服务器健康状态、性能指标和安全状况
 */
class ServerHealthCheck {
    private $results = [];
    private $thresholds = [
        'cpu_load' => 0.8,        // CPU使用率阈值 80%
        'memory_limit' => 0.9,    // 内存使用率阈值 90%
        'disk_limit' => 0.85,     // 磁盘使用率阈值 85%
        'response_time' => 2.0,   // 响应时间阈值(秒)
    ];
    public function __construct($thresholds = []) {
        if (!empty($thresholds)) {
            $this->thresholds = array_merge($this->thresholds, $thresholds);
        }
    }
    /**
     * 运行所有检查项目
     */
    public function runAllChecks() {
        $this->checkSystemInfo();
        $this->checkCPUUsage();
        $this->checkMemoryUsage();
        $this->checkDiskUsage();
        $this->checkNetworkConnection();
        $this->checkWebServerStatus();
        $this->checkPhpExtensions();
        $this->checkFilePermissions();
        $this->checkSecurity();
        $this->checkErrorLogs();
        return $this->generateReport();
    }
    /**
     * 检查系统基本信息
     */
    private function checkSystemInfo() {
        $this->results['system'] = [
            'os' => php_uname(),
            'php_version' => PHP_VERSION,
            'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown',
            'server_ip' => $_SERVER['SERVER_ADDR'] ?? gethostbyname(gethostname()),
            'uptime' => $this->getSystemUptime(),
            'date' => date('Y-m-d H:i:s')
        ];
    }
    /**
     * 检查CPU使用率
     */
    private function checkCPUUsage() {
        $cpuInfo = $this->getCPUUsage();
        $status = $cpuInfo['usage'] < ($this->thresholds['cpu_load'] * 100) ? 'OK' : 'WARNING';
        $this->results['cpu'] = [
            'status' => $status,
            'usage_percent' => round($cpuInfo['usage'], 2),
            'cores' => $cpuInfo['cores'],
            'details' => $cpuInfo['details']
        ];
    }
    /**
     * 获取CPU使用率
     */
    private function getCPUUsage() {
        // Linux系统实现
        if (PHP_OS_FAMILY === 'Linux') {
            $load = sys_getloadavg();
            $cores = $this->getCpuCoreCount();
            $usage = $load[0] / $cores * 100;
            return [
                'usage' => $usage,
                'cores' => $cores,
                'details' => "Load average: " . implode(', ', array_map(fn($v) => round($v, 2), $load))
            ];
        }
        // Windows系统实现(简化版)
        $info = exec('wmic cpu get loadpercentage /value');
        preg_match('/LoadPercentage=(\d+)/', $info, $matches);
        $usage = isset($matches[1]) ? (float)$matches[1] : 0;
        return [
            'usage' => $usage,
            'cores' => 1,
            'details' => 'Windows CPU info'
        ];
    }
    /**
     * 获取CPU核心数
     */
    private function getCpuCoreCount() {
        if (PHP_OS_FAMILY === 'Linux') {
            return (int)shell_exec('nproc') ?: 1;
        }
        return 1;
    }
    /**
     * 检查内存使用率
     */
    private function checkMemoryUsage() {
        $memoryInfo = $this->getMemoryUsage();
        $usagePercent = $memoryInfo['used'] / $memoryInfo['total'] * 100;
        $status = $usagePercent < ($this->thresholds['memory_limit'] * 100) ? 'OK' : 'WARNING';
        $this->results['memory'] = [
            'status' => $status,
            'total' => $this->formatBytes($memoryInfo['total']),
            'used' => $this->formatBytes($memoryInfo['used']),
            'free' => $this->formatBytes($memoryInfo['free']),
            'usage_percent' => round($usagePercent, 2),
            'details' => $memoryInfo['raw']
        ];
    }
    /**
     * 获取内存使用信息
     */
    private function getMemoryUsage() {
        if (PHP_OS_FAMILY === 'Linux') {
            $meminfo = file_get_contents('/proc/meminfo');
            preg_match('/MemTotal:\s+(\d+)/', $meminfo, $total);
            preg_match('/MemAvailable:\s+(\d+)/', $meminfo, $available);
            $totalBytes = $total[1] * 1024; // KB to bytes
            $availableBytes = $available[1] * 1024;
            return [
                'total' => $totalBytes,
                'used' => $totalBytes - $availableBytes,
                'free' => $availableBytes,
                'raw' => $meminfo
            ];
        }
        // Windows系统
        $output = [];
        exec('wmic OS get TotalVisibleMemorySize,FreePhysicalMemory /Value', $output);
        $totalKb = 0;
        $freeKb = 0;
        foreach ($output as $line) {
            if (strpos($line, 'TotalVisibleMemorySize=') !== false) {
                $totalKb = (int)str_replace('TotalVisibleMemorySize=', '', $line);
            }
            if (strpos($line, 'FreePhysicalMemory=') !== false) {
                $freeKb = (int)str_replace('FreePhysicalMemory=', '', $line);
            }
        }
        return [
            'total' => $totalKb * 1024,
            'used' => ($totalKb - $freeKb) * 1024,
            'free' => $freeKb * 1024,
            'raw' => 'Windows memory info'
        ];
    }
    /**
     * 检查磁盘使用率
     */
    private function checkDiskUsage() {
        $disks = [];
        $issues = [];
        if (PHP_OS_FAMILY === 'Linux') {
            $df = shell_exec('df -h');
            $lines = explode("\n", $df);
            array_shift($lines); // 移除标题行
            foreach ($lines as $line) {
                if (trim($line) === '') continue;
                $parts = preg_split('/\s+/', $line);
                if (count($parts) >= 5) {
                    $disk = [
                        'filesystem' => $parts[0],
                        'size' => $parts[1],
                        'used' => $parts[2],
                        'available' => $parts[3],
                        'usage_percent' => (int)str_replace('%', '', $parts[4]),
                        'mounted_on' => $parts[5] ?? ''
                    ];
                    $disks[] = $disk;
                    if ($disk['usage_percent'] > ($this->thresholds['disk_limit'] * 100)) {
                        $issues[] = "磁盘 {$disk['mounted_on']} 使用率超过阈值: {$disk['usage_percent']}%";
                    }
                }
            }
        } else {
            // Windows等其他系统检查
            $output = [];
            exec('wmic logicaldisk get deviceid,size,freespace /Value', $output);
            // 解析输出...
        }
        $this->results['disk'] = [
            'status' => empty($issues) ? 'OK' : 'WARNING',
            'disks' => $disks,
            'issues' => $issues
        ];
    }
    /**
     * 检查网络连接
     */
    private function checkNetworkConnection() {
        $connections = [];
        $issues = [];
        // 检查外部连接
        $externalHosts = [
            'google' => 'google.com',
            'github' => 'github.com'
        ];
        foreach ($externalHosts as $name => $host) {
            $pingTime = $this->pingHost($host);
            $connections[$name] = $pingTime;
            if ($pingTime === false) {
                $issues[] = "无法连接到 $host";
            }
        }
        // 检查数据库连接(如果配置了)
        if (defined('DB_HOST')) {
            $dbConnection = $this->checkDatabaseConnection();
            $connections['database'] = $dbConnection;
            if (!$dbConnection['success']) {
                $issues[] = "数据库连接失败";
            }
        }
        $this->results['network'] = [
            'status' => empty($issues) ? 'OK' : 'WARNING',
            'connections' => $connections,
            'issues' => $issues
        ];
    }
    /**
     * Ping外部主机
     */
    private function pingHost($host) {
        $startTime = microtime(true);
        if (PHP_OS_FAMILY === 'Linux') {
            $output = [];
            exec("ping -c 1 -w 2 $host", $output, $returnCode);
            if ($returnCode === 0) {
                $time = microtime(true) - $startTime;
                return round($time * 1000); // 毫秒
            }
            return false;
        } else {
            // Windows
            $output = [];
            exec("ping -n 1 -w 2000 $host", $output, $returnCode);
            if ($returnCode === 0) {
                $time = microtime(true) - $startTime;
                return round($time * 1000);
            }
            return false;
        }
    }
    /**
     * 检查数据库连接
     */
    private function checkDatabaseConnection() {
        try {
            $pdo = new PDO(
                'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME,
                DB_USER,
                DB_PASS,
                [PDO::ATTR_TIMEOUT => 2]
            );
            return [
                'success' => true,
                'info' => 'Database connection OK'
            ];
        } catch (Exception $e) {
            return [
                'success' => false,
                'info' => 'Database connection failed: ' . $e->getMessage()
            ];
        }
    }
    /**
     * 检查Web服务器状态
     */
    private function checkWebServerStatus() {
        $issues = [];
        $serverInfo = [];
        // 检查Apache/Nginx进程
        if (PHP_OS_FAMILY === 'Linux') {
            foreach (['apache2', 'nginx', 'httpd'] as $service) {
                $output = [];
                exec("ps aux | grep -v grep | grep $service", $output);
                if (!empty($output)) {
                    $serverInfo[$service] = 'Running';
                } else {
                    $serverInfo[$service] = 'Not running';
                    $issues[] = "$service is not running";
                }
            }
        }
        // 检查PHP-FPM
        if (PHP_OS_FAMILY === 'Linux') {
            $output = [];
            exec("ps aux | grep -v grep | grep php-fpm", $output);
            $serverInfo['php-fpm'] = !empty($output) ? 'Running' : 'Not running';
            if (empty($output)) {
                $issues[] = 'PHP-FPM is not running';
            }
        }
        $this->results['web_server'] = [
            'status' => empty($issues) ? 'OK' : 'WARNING',
            'services' => $serverInfo,
            'issues' => $issues
        ];
    }
    /**
     * 检查PHP扩展
     */
    private function checkPhpExtensions() {
        $requiredExtensions = [
            'mysqli', 'pdo_mysql', 'curl', 'json', 'gd', 'mbstring',
            'xml', 'zip', 'openssl', 'redis', 'memcached'
        ];
        $extensions = [];
        $missingExtensions = [];
        foreach ($requiredExtensions as $ext) {
            $extensions[$ext] = extension_loaded($ext) ? 'Enabled' : 'Disabled';
            if (!extension_loaded($ext)) {
                $missingExtensions[] = $ext;
            }
        }
        $this->results['php_extensions'] = [
            'status' => empty($missingExtensions) ? 'OK' : 'WARNING',
            'extensions' => $extensions,
            'missing' => $missingExtensions
        ];
    }
    /**
     * 检查文件权限
     */
    private function checkFilePermissions() {
        $criticalPaths = [
            'web_root' => $_SERVER['DOCUMENT_ROOT'] ?? '.',
            'upload_dir' => 'uploads',
            'log_dir' => 'logs',
            'config' => 'config.php'
        ];
        $issues = [];
        $permissions = [];
        foreach ($criticalPaths as $name => $path) {
            if (file_exists($path)) {
                $perms = fileperms($path);
                $writable = is_writable($path);
                $permissions[$name] = [
                    'path' => $path,
                    'permissions' => substr(sprintf('%o', $perms), -4),
                    'writable' => $writable
                ];
                if (!$writable) {
                    $issues[] = "目录/文件 $path 不可写";
                }
            }
        }
        // 检查敏感文件是否可访问
        $sensitiveFiles = ['.env', 'config.php', 'database.sql'];
        foreach ($sensitiveFiles as $file) {
            if (file_exists($file) && !$this->isFileProtected($file)) {
                $issues[] = "敏感文件 $file 可能暴露在Web环境下";
            }
        }
        $this->results['permissions'] = [
            'status' => empty($issues) ? 'OK' : 'WARNING',
            'permissions' => $permissions,
            'issues' => $issues
        ];
    }
    /**
     * 检查文件是否受保护
     */
    private function isFileProtected($file) {
        // 检查是否在web根目录之外
        $absolutePath = realpath($file);
        $webRoot = realpath($_SERVER['DOCUMENT_ROOT'] ?? '.');
        return strpos($absolutePath, $webRoot) !== 0;
    }
    /**
     * 安全检查
     */
    private function checkSecurity() {
        $securityIssues = [];
        $checks = [];
        // 检查PHP版本安全性
        $phpVersion = PHP_VERSION;
        $checks['php_version'] = "PHP版本: $phpVersion";
        if (version_compare($phpVersion, '7.4', '<')) {
            $securityIssues[] = "PHP版本过低,建议升级到7.4以上";
        }
        // 检查显示错误设置
        $displayErrors = ini_get('display_errors');
        $checks['display_errors'] = $displayErrors ? 'Enabled' : 'Disabled';
        if ($displayErrors) {
            $securityIssues[] = "display_errors已开启,建议在生产环境关闭";
        }
        // 检查错误报告级别
        $errorReporting = error_reporting();
        $checks['error_reporting'] = $errorReporting;
        // 检查文件上传设置
        $fileUploads = ini_get('file_uploads');
        $checks['file_uploads'] = $fileUploads ? 'Enabled' : 'Disabled';
        // 检查open_basedir
        $openBasedir = ini_get('open_basedir');
        $checks['open_basedir'] = $openBasedir ? $openBasedir : 'Not Set';
        if (empty($openBasedir)) {
            $securityIssues[] = "open_basedir未设置,可能存在目录遍历风险";
        }
        // 检查关键函数是否被禁用
        $dangerousFunctions = ['exec', 'system', 'passthru', 'shell_exec', 'proc_open'];
        $disabledFunctions = array_filter(explode(',', ini_get('disable_functions')));
        foreach ($dangerousFunctions as $func) {
            if (!in_array(trim($func), $disabledFunctions)) {
                $checks["func_$func"] = "未禁用 $func()";
                $securityIssues[] = "高风险函数 $func() 未被禁用";
            }
        }
        // 检查HTTPS
        $https = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
        $checks['https'] = $https ? 'Enabled' : 'Disabled';
        if (!$https && PHP_SAPI !== 'cli') {
            $securityIssues[] = "当前未使用HTTPS连接";
        }
        $this->results['security'] = [
            'status' => empty($securityIssues) ? 'OK' : 'WARNING',
            'checks' => $checks,
            'issues' => $securityIssues
        ];
    }
    /**
     * 检查错误日志
     */
    private function checkErrorLogs() {
        $logFile = ini_get('error_log');
        $issues = [];
        $recentErrors = [];
        if (file_exists($logFile)) {
            $logSize = filesize($logFile);
            $mtime = filemtime($logFile);
            // 读取最后100行日志
            $lines = $this->getLastLines($logFile, 100);
            foreach ($lines as $line) {
                if (preg_match('/\[error\]|\[warning\]|Fatal error/i', $line)) {
                    $recentErrors[] = trim($line);
                    if (strpos($line, 'Fatal error') !== false) {
                        $issues[] = "发现致命错误: $line";
                    }
                }
            }
            $this->results['error_log'] = [
                'status' => empty($issues) ? 'OK' : 'WARNING',
                'log_file' => $logFile,
                'log_size' => $this->formatBytes($logSize),
                'last_modified' => date('Y-m-d H:i:s', $mtime),
                'recent_errors' => array_slice($recentErrors, -5),
                'issues' => $issues
            ];
        } else {
            $this->results['error_log'] = [
                'status' => 'WARNING',
                'issues' => ['未找到错误日志文件: ' . $logFile]
            ];
        }
    }
    /**
     * 读取文件最后几行
     */
    private function getLastLines($file, $lines = 100) {
        if (PHP_OS_FAMILY === 'Linux') {
            return explode("\n", shell_exec("tail -n $lines $file"));
        }
        // 其他系统使用PHP实现
        $content = file_get_contents($file);
        $contentLines = explode("\n", $content);
        return array_slice($contentLines, -$lines);
    }
    /**
     * 生成报告
     */
    private function generateReport() {
        $summary = [
            'total_checks' => 0,
            'ok' => 0,
            'warnings' => 0,
            'errors' => 0
        ];
        foreach ($this->results as $category => $result) {
            if (isset($result['status'])) {
                $summary['total_checks']++;
                switch ($result['status']) {
                    case 'OK':
                        $summary['ok']++;
                        break;
                    case 'WARNING':
                        $summary['warnings']++;
                        break;
                    case 'ERROR':
                        $summary['errors']++;
                        break;
                }
            }
        }
        // 设置整体状态
        $overallStatus = 'OK';
        if ($summary['errors'] > 0) {
            $overallStatus = 'ERROR';
        } elseif ($summary['warnings'] > 0) {
            $overallStatus = 'WARNING';
        }
        return [
            'overall_status' => $overallStatus,
            'summary' => $summary,
            'timestamp' => date('Y-m-d H:i:s'),
            'details' => $this->results
        ];
    }
    /**
     * 格式化字节
     */
    private function formatBytes($bytes, $precision = 2) {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        $bytes /= pow(1024, $pow);
        return round($bytes, $precision) . ' ' . $units[$pow];
    }
    /**
     * 获取系统运行时间
     */
    private function getSystemUptime() {
        if (PHP_OS_FAMILY === 'Linux') {
            $uptime = shell_exec('cat /proc/uptime');
            $seconds = floatval(explode(' ', $uptime)[0]);
            $days = floor($seconds / 86400);
            $hours = floor(($seconds % 86400) / 3600);
            $minutes = floor(($seconds % 3600) / 60);
            return "$days天 $hours小时 $minutes分钟";
        }
        return 'System uptime info unavailable';
    }
}
// 使用方法示例
if (PHP_SAPI === 'cli') {
    // 命令行模式
    $healthCheck = new ServerHealthCheck();
    $report = $healthCheck->runAllChecks();
    echo json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . PHP_EOL;
}

数据库巡检脚本

database_check.php

<?php
/**
 * 数据库巡检脚本
 */
function checkDatabaseHealth() {
    // 数据库配置
    $dbConfig = [
        'host' => 'localhost',
        'name' => 'your_database',
        'user' => 'your_user',
        'pass' => 'your_password',
        'port' => 3306
    ];
    $results = [
        'status' => 'OK',
        'checks' => []
    ];
    try {
        $pdo = new PDO(
            "mysql:host={$dbConfig['host']};dbname={$dbConfig['name']};charset=utf8mb4",
            $dbConfig['user'],
            $dbConfig['pass'],
            [
                PDO::ATTR_TIMEOUT => 5,
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
            ]
        );
        // 1. 数据库版本
        $version = $pdo->query('SELECT VERSION()')->fetchColumn();
        $results['checks']['version'] = $version;
        // 2. 数据库状态
        $status = $pdo->query('SHOW STATUS')->fetchAll(PDO::FETCH_KEY_PAIR);
        $results['checks']['qps'] = $status['Questions'] ?? 'N/A';  // 查询次数
        // 3. 连接数
        $connections = $pdo->query('SHOW STATUS LIKE "Threads_connected"')->fetch();
        $maxConnections = $pdo->query('SHOW VARIABLES LIKE "max_connections"')->fetch();
        $currentConn = (int)$connections['Value'];
        $maxConn = (int)$maxConnections['Value'];
        $usagePercent = ($currentConn / $maxConn) * 100;
        $results['checks']['connections'] = [
            'current' => $currentConn,
            'max' => $maxConn,
            'usage_percent' => round($usagePercent, 2)
        ];
        if ($usagePercent > 85) {
            $results['status'] = 'WARNING';
            $results['issues'][] = "数据库连接数使用率过高: {$usagePercent}%";
        }
        // 4. 慢查询
        $slowQueries = $pdo->query('SHOW STATUS LIKE "Slow_queries"')->fetch();
        $results['checks']['slow_queries'] = $slowQueries['Value'] ?? 'N/A';
        // 5. InnoDB状态
        $innodbStatus = $pdo->query('SHOW ENGINE INNODB STATUS')->fetch();
        if ($innodbStatus) {
            preg_match('/Active transactions: (\d+)/', $innodbStatus['Status'], $matches);
            $results['checks']['active_transactions'] = $matches[1] ?? 'N/A';
        }
        // 6. 数据库表检查
        $tables = $pdo->query('SHOW TABLES')->fetchAll(PDO::FETCH_COLUMN);
        $brokenTables = [];
        foreach ($tables as $table) {
            $checkResult = $pdo->query("CHECK TABLE $table")->fetch();
            if ($checkResult['Msg_type'] === 'error') {
                $brokenTables[] = $table;
            }
        }
        $results['checks']['tables'] = [
            'total' => count($tables),
            'broken' => $brokenTables
        ];
        // 7. 数据库大小
        $dbSize = $pdo->query(
            "SELECT table_schema AS 'database',
             ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'size_mb'
             FROM information_schema.tables
             WHERE table_schema = '{$dbConfig['name']}'
             GROUP BY table_schema"
        )->fetch();
        $results['checks']['database_size'] = $dbSize['size_mb'] . ' MB';
        // 8. 最后一次备份时间
        $backupDir = '/path/to/backup/dir';  // 配置备份目录
        if (is_dir($backupDir)) {
            $backupFiles = glob($backupDir . '/*');
            if (!empty($backupFiles)) {
                $latestBackup = max(array_map('filemtime', $backupFiles));
                $daysSinceBackup = (time() - $latestBackup) / 86400;
                $results['checks']['last_backup'] = date('Y-m-d H:i:s', $latestBackup);
                $results['checks']['backup_age_days'] = round($daysSinceBackup, 2);
                if ($daysSinceBackup > 1) {
                    $results['status'] = 'WARNING';
                    $results['issues'][] = "数据库超过1天未备份";
                }
            }
        }
    } catch (PDOException $e) {
        $results['status'] = 'ERROR';
        $results['message'] = '数据库连接失败: ' . $e->getMessage();
    }
    return $results;
}
// 执行检查
$report = checkDatabaseHealth();
echo json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);

配置文件和定时任务

config.php

<?php
// 数据库配置(用于巡检脚本)
define('DB_HOST', 'localhost');
define('DB_NAME', 'your_database');
define('DB_USER', 'your_user');
define('DB_PASS', 'your_password');
// 邮件通知配置
define('MAIL_ENABLED', true);
define('MAIL_TO', 'admin@example.com');
define('MAIL_FROM', 'monitor@example.com');
// Webhook通知配置
define('WEBHOOK_ENABLED', true);
define('WEBHOOK_URL', 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL');
// 短信通知配置(示例)
define('SMS_ENABLED', false);

notification.php

<?php
/**
 * 通知发送功能
 */
class NotificationCenter {
    public static function sendReport($report) {
        $messages = [];
        if ($report['overall_status'] !== 'OK') {
            // 发送邮件
            if (defined('MAIL_ENABLED') && MAIL_ENABLED) {
                self::sendEmail($report);
            }
            // 发送Webhook
            if (defined('WEBHOOK_ENABLED') && WEBHOOK_ENABLED) {
                self::sendWebhook($report);
            }
        }
        return true;
    }
    private static function sendEmail($report) {
        $subject = "[{$report['overall_status']}] 服务器巡检报告 - " . date('Y-m-d H:i:s');
        // 生成HTML报告
        $htmlReport = self::generateHtmlReport($report);
        $headers = "MIME-Version: 1.0\r\n";
        $headers .= "Content-type: text/html; charset=utf-8\r\n";
        $headers .= "From: " . MAIL_FROM . "\r\n";
        // 使用mail函数或PHPMailer
        mail(MAIL_TO, $subject, $htmlReport, $headers);
    }
    private static function sendWebhook($report) {
        $payload = [
            'text' => "🚨 *服务器巡检提醒*\n" .
                     "*状态:* {$report['overall_status']}\n" .
                     "*时间:* {$report['timestamp']}\n" .
                     "*警告数:* {$report['summary']['warnings']}\n" .
                     "*错误数:* {$report['summary']['errors']}"
        ];
        $ch = curl_init(WEBHOOK_URL);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_exec($ch);
        curl_close($ch);
    }
    private static function generateHtmlReport($report) {
        $html = '<h2>服务器巡检报告</h2>';
        $html .= "<p>状态: <strong>{$report['overall_status']}</strong></p>";
        $html .= "<p>时间: {$report['timestamp']}</p>";
        foreach ($report['details'] as $category => $details) {
            $html .= "<h3>{$category}</h3>";
            if (isset($details['status'])) {
                $html .= "<p>状态: {$details['status']}</p>";
            }
            if (isset($details['issues']) && !empty($details['issues'])) {
                $html .= '<ul>';
                foreach ($details['issues'] as $issue) {
                    $html .= "<li>$issue</li>";
                }
                $html .= '</ul>';
            }
        }
        return $html;
    }
}
// 如果报告完成,发送通知
NotificationCenter::sendReport($report);

定时任务配置

crontab 配置示例

# 每天凌晨2点执行服务器巡检
0 2 * * * php /path/to/server_check.php >> /var/log/php_check.log 2>&1
# 每30分钟检查一次Web服务状态
*/30 * * * * php /path/to/web_service_check.php
# 每天检查数据库状态
30 3 * * * php /path/to/database_check.php
# 每周日完整巡检
0 4 * * 0 php /path/to/full_check.php

使用说明

配置文件

  1. 将上述代码保存为对应文件
  2. 修改 config.php 中的数据库配置和通知配置
  3. 测试运行:
    php server_check.php

主要功能

  • 系统检查: CPU、内存、磁盘使用情况
  • 性能监控: 响应时间、负载均衡
  • 安全扫描: 敏感文件、危险函数、安全配置
  • 数据库检查: 连接数、慢查询、表完整性
  • Web服务检查: Apache/Nginx、PHP-FPM状态

通知方式

  • 邮件通知
  • Webhook(如Slack、钉钉)
  • 可扩展短信通知

这个巡检脚本可以根据您的具体需求进行调整和扩展。

抱歉,评论功能暂时关闭!