info('DB 백업 상태 확인 시작...'); $statusFile = $this->option('path') ? rtrim($this->option('path'), '/') . '/.backup_status' : env('BACKUP_STATUS_FILE', '/data/backup/mysql/.backup_status'); $errors = []; // 1. 상태 파일 존재 여부 if (! file_exists($statusFile)) { $errors[] = '백업 상태 파일 없음: ' . $statusFile; $this->reportErrors($monitorService, $errors); return self::FAILURE; } $status = json_decode(file_get_contents($statusFile), true); if (json_last_error() !== JSON_ERROR_NONE) { $errors[] = '상태 파일 JSON 파싱 실패: ' . json_last_error_msg(); $this->reportErrors($monitorService, $errors); return self::FAILURE; } // 2. last_run이 25시간 이내인지 $lastRun = strtotime($status['last_run'] ?? ''); if (! $lastRun || (time() - $lastRun) > 25 * 3600) { $lastRunStr = $status['last_run'] ?? 'unknown'; $errors[] = "마지막 백업이 25시간 초과: {$lastRunStr}"; } // 3. status가 success인지 if (($status['status'] ?? '') !== 'success') { $errors[] = '백업 상태 실패: ' . ($status['status'] ?? 'unknown'); } // 4. 각 DB 백업 파일 크기 검증 $minSizes = [ 'sam' => (int) env('BACKUP_MIN_SIZE_SAM', 1048576), 'sam_stat' => (int) env('BACKUP_MIN_SIZE_STAT', 102400), ]; $databases = $status['databases'] ?? []; foreach ($minSizes as $dbName => $minSize) { if (! isset($databases[$dbName])) { $errors[] = "{$dbName} DB 백업 정보 없음"; continue; } $sizeBytes = $databases[$dbName]['size_bytes'] ?? 0; if ($sizeBytes < $minSize) { $errors[] = "{$dbName} 백업 파일 크기 부족: {$sizeBytes} bytes (최소 {$minSize})"; } } // 결과 처리 if (! empty($errors)) { $this->reportErrors($monitorService, $errors); return self::FAILURE; } $this->info('✅ DB 백업 상태 정상'); Log::info('db:backup-check 정상', [ 'last_run' => $status['last_run'], 'databases' => array_keys($databases), ]); return self::SUCCESS; } private function reportErrors(StatMonitorService $monitorService, array $errors): void { $errorMessage = implode("\n", $errors); $this->error('❌ DB 백업 이상 감지:'); foreach ($errors as $error) { $this->error(" - {$error}"); } // stat_alerts에 기록 $monitorService->recordBackupFailure( '[backup] DB 백업 이상 감지', $errorMessage ); // Slack 알림 전송 app(SlackNotificationService::class)->sendBackupAlert( 'DB 백업 이상 감지', $errorMessage ); Log::error('db:backup-check 실패', ['errors' => $errors]); } }