using Microsoft.Extensions.Hosting; namespace Service; /// /// 日志清理后台服务 /// public class LogCleanupService(ILogger logger) : BackgroundService { private readonly TimeSpan _checkInterval = TimeSpan.FromHours(24); // 每24小时检查一次 private const int RetentionDays = 30; // 保留30天的日志 protected override async Task ExecuteAsync(CancellationToken stoppingToken) { logger.LogInformation("日志清理服务已启动"); // 启动时立即执行一次清理 await CleanupOldLogsAsync(); // 定期清理 while (!stoppingToken.IsCancellationRequested) { try { await Task.Delay(_checkInterval, stoppingToken); await CleanupOldLogsAsync(); } catch (OperationCanceledException) { // 服务正在停止 break; } catch (Exception ex) { logger.LogError(ex, "清理日志时发生错误"); } } logger.LogInformation("日志清理服务已停止"); } /// /// 清理过期的日志文件 /// private async Task CleanupOldLogsAsync() { await Task.Run(() => { try { var logDirectory = Path.Combine(Directory.GetCurrentDirectory(), "logs"); if (!Directory.Exists(logDirectory)) { logger.LogWarning("日志目录不存在: {LogDirectory}", logDirectory); return; } var cutoffDate = DateTime.Now.AddDays(-RetentionDays); var logFiles = Directory.GetFiles(logDirectory, "log-*.txt"); var deletedCount = 0; foreach (var logFile in logFiles) { try { var fileName = Path.GetFileNameWithoutExtension(logFile); var dateStr = fileName.Replace("log-", ""); // 尝试解析日期 (格式: yyyyMMdd) if (DateTime.TryParseExact(dateStr, "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out var logDate)) { if (logDate < cutoffDate) { File.Delete(logFile); deletedCount++; logger.LogInformation("已删除过期日志文件: {LogFile} (日期: {LogDate})", Path.GetFileName(logFile), logDate.ToString("yyyy-MM-dd")); } } } catch (Exception ex) { logger.LogError(ex, "删除日志文件失败: {LogFile}", logFile); } } if (deletedCount > 0) { logger.LogInformation("日志清理完成,共删除 {DeletedCount} 个过期日志文件(保留 {RetentionDays} 天)", deletedCount, RetentionDays); } else { logger.LogDebug("没有需要清理的过期日志文件"); } } catch (Exception ex) { logger.LogError(ex, "清理日志过程中发生错误"); } }); } }