CearDirService.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Channels;
  7. using System.Threading.Tasks;
  8. using Ips.Library.Basic;
  9. using Ips.Library.DxpLib;
  10. using Microsoft.Extensions.Hosting;
  11. namespace Ips.Service.CapServer
  12. {
  13. /// <summary>
  14. /// 数据清理服务(每隔5分钟扫描一次)
  15. /// </summary>
  16. public class CearDirService : BackgroundService
  17. {
  18. protected override async Task ExecuteAsync(CancellationToken stoppingToken)
  19. {
  20. await Task.Delay(5000, stoppingToken);//延迟一会儿让webbapi先启动
  21. IpsLogger.Info($"启动采集专用目录数据清理功能...");
  22. await Task.Run(async () =>
  23. {
  24. #region 读取清理目录配置信息
  25. string dataClearStr = ToolConfig.GetAppSetting("ClearDir");
  26. var dataClears = dataClearStr.Split(new string[] { ";", ";" }, StringSplitOptions.RemoveEmptyEntries)
  27. .Select(p => p.ToLower()).ToList();
  28. if (!dataClears.Contains(AppConst.DataDir))
  29. dataClears.Add(AppConst.DataDir);
  30. #endregion
  31. #region 检测有效的清理目录并读取清理条件
  32. List<string> list = new List<string>();
  33. foreach (var item in dataClears)
  34. {
  35. var root = Path.GetPathRoot(item);
  36. DriveInfo drive = new DriveInfo(root);
  37. if (!drive.IsReady)
  38. {
  39. continue;
  40. }
  41. if (Directory.Exists(item))
  42. {
  43. list.Add(item);
  44. }
  45. }
  46. if (!list.Any())
  47. {
  48. IpsLogger.Warn($"配置文件中的数据清理目录无效");
  49. return;
  50. }
  51. float maxPercent = ToolConfig.GetAppSetting("ClearCondition", 0.2f);
  52. var clearHours = (int)ToolConfig.GetAppSetting("ClearHours", 12d);
  53. if (clearHours < 1)
  54. {
  55. clearHours = 1;
  56. }
  57. IpsLogger.Info($"已启动目录[{string.Join(";", list)}]自动清理,清理条件=可用空间不足{(int)(maxPercent * 100)}%");
  58. #endregion
  59. //缓存每个目录上次清理的文件最大的一个写入时间
  60. var prevClearTime = new Dictionary<string, DateTime>();
  61. foreach (var item in list)
  62. {
  63. prevClearTime[item] = DateTime.MinValue;
  64. }
  65. while (!stoppingToken.IsCancellationRequested)
  66. {
  67. IpsLogger.Info($"开始数据清理...");
  68. #region 从上次开始每个目录清理一定的数据(ClearHours)
  69. int delFileCount = 0;
  70. try
  71. {
  72. var driveFolders = list.GroupBy(m => Path.GetPathRoot(m).ToUpper());
  73. foreach (var driveFolder in driveFolders)//like D:\ E:\
  74. {
  75. if (stoppingToken.IsCancellationRequested) break;
  76. DriveInfo drive = new DriveInfo(driveFolder.Key);
  77. while (drive.TotalFreeSpace / (drive.TotalSize * 1.0f) <= maxPercent)
  78. {
  79. foreach (var item in driveFolder)//like D:\data E:\data
  80. {
  81. IpsLogger.Info($"正在清理[{item}]中的数据...");
  82. var fsList = Directory.EnumerateFiles(item, "*", SearchOption.AllDirectories).Select(p => new FileInfo(p));
  83. if (!fsList.Any())
  84. {
  85. IpsLogger.Warn($"{drive.ToString().Substring(0, 1)}盘空间不足,但目录{item}没有数据,跳过此目录");
  86. }
  87. else
  88. {
  89. if (prevClearTime[item] == DateTime.MinValue)
  90. prevClearTime[item] = fsList.Min(p => p.LastWriteTime);
  91. var maxTime = prevClearTime[item].AddHours(clearHours);
  92. if (maxTime <= prevClearTime[item])
  93. {
  94. //clearHours配置为0或负数时一次删所有文件
  95. maxTime = DateTime.MaxValue;
  96. }
  97. //每次清理从上次清理结束时间开始,防止有些删不掉的文件阻止删除文件
  98. var clearFiles = fsList.Where(m => m.LastWriteTime >= prevClearTime[item] && m.LastWriteTime <= maxTime).OrderBy(m => m.LastWriteTime);
  99. foreach (var fsItem in clearFiles)
  100. {
  101. try
  102. {
  103. if (stoppingToken.IsCancellationRequested) break;
  104. fsItem.Delete();
  105. delFileCount++;
  106. }
  107. catch (Exception ex)
  108. {
  109. IpsLogger.Error($"删除文件{fsItem.Name}出错", ex);
  110. }
  111. }
  112. prevClearTime[item] = maxTime;
  113. }
  114. }
  115. }
  116. }
  117. }
  118. catch (Exception ex)
  119. {
  120. IpsLogger.Error($"清理数据异常", ex);
  121. }
  122. #endregion
  123. #region 清理空目录
  124. int delDirCount = 0;
  125. foreach (var name in list)
  126. {
  127. string clearDir = Path.Combine(AppContext.BaseDirectory, name);
  128. try
  129. {
  130. var dirs = Directory.EnumerateDirectories(clearDir, "*", SearchOption.AllDirectories);
  131. foreach (var item in dirs)
  132. {
  133. DirectoryInfo dir = new DirectoryInfo(item);
  134. if (dir.EnumerateFiles().Any()) continue;
  135. //删除5分钟以前创建的空目录
  136. if ((DateTime.Now - dir.CreationTime).TotalMinutes > 5)
  137. {
  138. try
  139. {
  140. dir.Delete();
  141. delDirCount++;
  142. }
  143. catch (Exception ex)
  144. {
  145. IpsLogger.Error($"删除空目录{dir.Name}异常", ex);
  146. }
  147. }
  148. }
  149. }
  150. catch (Exception ex)
  151. {
  152. IpsLogger.Error($"删除{name}目录中的空目录出错", ex);
  153. }
  154. }
  155. #endregion
  156. IpsLogger.Info($"本次清理数据结束,删除{delFileCount}个文件,删除{delDirCount}个空目录");
  157. await Task.Delay(5 * 60 * 1000, stoppingToken);
  158. }
  159. }, stoppingToken);
  160. }
  161. }
  162. }