pbootcms定期自动清理缓存runtime

    pbootcms更改index.php,新增:

    // 引入runtime周清理工具
    require dirname(__FILE__) . '/core/runtime_weekly_cleaner.php';   
    // 引用内核启动文件
    require dirname(__FILE__) . '/core/start.php';

    以下代码首次访问会执行一次,然后定期会清理并做日志记录,日志在/core/data/clean_log目录,runtime_weekly_cleaner.php文件内容:

    <?php
    /**
     * Runtime目录定期清理工具(修复版)
     * 修复重点:标记文件过期机制、权限检查、日志增强
     */
    
    if (!defined('IS_INDEX')) {
        exit('Access Denied!');
    }
    
    class RuntimeCleaner {
        
        private $config;
        
        public function __construct() {
            $this->config = [
                'runtime_path' => realpath(dirname(__DIR__) . '/runtime/') . '/',
                'log_path' => realpath(__DIR__ . '/data/clean_log/') . '/',
                'flag_file' => __DIR__ . '/data/clean_log/.cleaned'
            ];
        }
        
        public function execute() {
            $this->ensureDirectories();
            
            $flagFile = $this->config['flag_file'];
            // 检查标记文件是否存在且未过期(3天)
            if (file_exists($flagFile) && (time() - filemtime($flagFile)) < 3 * 86400) {
                return;
            }
            
            $logContent = $this->generateLogHeader();
            
            try {
                $logContent .= $this->performCleanup();
                touch($flagFile);  // 更新标记文件时间戳
                $logContent .= "标记文件已更新: " . date('Y-m-d H:i:s') . "\n";
            } catch (Exception $e) {
                $logContent .= "清理失败: " . $e->getMessage() . "\n";
                $this->writeLog($logContent);
                throw $e;  // 重新抛出异常以便外部捕获
            }
            
            $this->writeLog($logContent);
        }
        
        private function ensureDirectories() {
            // 创建日志目录(如果不存在)
            if (!file_exists($this->config['log_path'])) {
                if (!mkdir($this->config['log_path'], 0755, true)) {
                    throw new Exception("无法创建日志目录: " . $this->config['log_path']);
                }
                chmod($this->config['log_path'], 0755);
            }
            
            // 验证runtime目录
            if (!is_dir($this->config['runtime_path'])) {
                throw new Exception("Runtime目录不存在: " . $this->config['runtime_path']);
            }
            
            // 验证目录可写性
            if (!is_writable($this->config['runtime_path'])) {
                throw new Exception("Runtime目录不可写: " . $this->config['runtime_path']);
            }
        }
        
        private function generateLogHeader() {
            return sprintf(
                "[%s] 开始清理任务\n运行时目录: %s\n磁盘剩余空间: %s\n",
                date('Y-m-d H:i:s'),
                $this->config['runtime_path'],
                $this->formatBytes(disk_free_space($this->config['runtime_path']))
            );
        }
        
        private function performCleanup() {
            $stats = ['folders' => 0, 'files' => 0, 'size' => 0];
            $logContent = "";
            
            $items = new DirectoryIterator($this->config['runtime_path']);
            
            foreach ($items as $item) {
                if ($item->isDot()) continue;
                
                $path = $item->getPathname();
                
                try {
                    if ($item->isDir()) {
                        $this->deleteDirectory($path, $stats);
                        $stats['folders']++;
                        $logContent .= "已删除文件夹: " . $item->getFilename() . "\n";
                    } elseif ($item->isFile()) {
                        $stats['files']++;
                        $stats['size'] += $item->getSize();
                        if (!unlink($path)) {
                            throw new Exception("无法删除文件: " . $path);
                        }
                    }
                } catch (Exception $e) {
                    $logContent .= "操作失败: " . $e->getMessage() . "\n";
                }
            }
            
            return $logContent . sprintf(
                "清理完成\n删除文件夹: %d 个\n删除文件: %d 个\n释放空间: %s\n剩余空间: %s\n",
                $stats['folders'],
                $stats['files'],
                $this->formatBytes($stats['size']),
                $this->formatBytes(disk_free_space($this->config['runtime_path']))
            );
        }
        
        private function deleteDirectory($path, &$stats) {
            $iterator = new RecursiveDirectoryIterator(
                $path,
                FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS
            );
            
            $files = new RecursiveIteratorIterator(
                $iterator,
                RecursiveIteratorIterator::CHILD_FIRST
            );
            
            foreach ($files as $file) {
                try {
                    if ($file->isFile()) {
                        $stats['files']++;
                        $stats['size'] += $file->getSize();
                        if (!unlink($file->getRealPath())) {
                            throw new Exception("无法删除文件: " . $file->getPathname());
                        }
                    } elseif ($file->isDir()) {
                        if (!rmdir($file->getRealPath())) {
                            throw new Exception("无法删除目录: " . $file->getPathname());
                        }
                    }
                } catch (Exception $e) {
                    throw new Exception("删除操作失败: " . $e->getMessage());
                }
            }
            
            if (!rmdir($path)) {
                throw new Exception("无法删除主目录: " . $path);
            }
        }
        
        private function writeLog($content) {
            $logFile = $this->config['log_path'] . 'clean_log_' . date('Y-m') . '.log';
            if (file_put_contents($logFile, $content, FILE_APPEND | LOCK_EX) === false) {
                throw new Exception("无法写入日志文件: " . $logFile);
            }
        }
        
        private function formatBytes($bytes) {
            if ($bytes <= 0) return '0 B';
            $units = ['B', 'KB', 'MB', 'GB', 'TB'];
            $pow = floor(log($bytes, 1024));
            $pow = min($pow, count($units) - 1);
            return round($bytes / (1024 ** $pow), 2) . ' ' . $units[$pow];
        }
    }
    
    // 执行清理(建议通过cron调用)
    try {
        (new RuntimeCleaner())->execute();
    } catch (Exception $e) {
        error_log("Runtime清理错误: " . $e->getMessage());
    }