CleanSizeRotatingLogsCommand.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <?php
  2. namespace UCore\Commands;
  3. use Illuminate\Console\Command;
  4. use Illuminate\Support\Facades\File;
  5. use Carbon\Carbon;
  6. /**
  7. * 清理 size_rotating_daily 日志文件的计划任务
  8. *
  9. * 功能:
  10. * 1. 删除超过指定天数的日志备份文件
  11. * 2. 支持自定义保留天数(默认6天)
  12. * 3. 提供详细的清理报告
  13. */
  14. class CleanSizeRotatingLogsCommand extends Command
  15. {
  16. /**
  17. * 命令签名
  18. *
  19. * @var string
  20. */
  21. protected $signature = 'ucore:clean-size-rotating-logs {--days=6 : 保留的天数} {--dry-run : 仅显示将要删除的文件,不实际删除}';
  22. /**
  23. * 命令描述
  24. *
  25. * @var string
  26. */
  27. protected $description = '清理 size_rotating_daily 目录中超过指定天数的日志备份文件';
  28. /**
  29. * 日志备份目录路径
  30. *
  31. * @var string
  32. */
  33. protected string $logBackupPath;
  34. /**
  35. * 构造函数
  36. */
  37. public function __construct()
  38. {
  39. parent::__construct();
  40. $this->logBackupPath = storage_path('logs/size_rotating_daily');
  41. }
  42. /**
  43. * 执行命令
  44. *
  45. * @return int
  46. */
  47. public function handle(): int
  48. {
  49. $days = (int) $this->option('days');
  50. $dryRun = $this->option('dry-run');
  51. $this->info("开始清理 size_rotating_daily 日志文件...");
  52. $this->info("保留天数: {$days} 天");
  53. $this->info("备份目录: {$this->logBackupPath}");
  54. if ($dryRun) {
  55. $this->warn("*** 这是一次试运行,不会实际删除文件 ***");
  56. }
  57. // 检查目录是否存在
  58. if (!File::exists($this->logBackupPath)) {
  59. $this->warn("备份目录不存在: {$this->logBackupPath}");
  60. return Command::SUCCESS;
  61. }
  62. // 计算截止日期
  63. $cutoffDate = Carbon::now()->subDays($days);
  64. $this->info("将删除 {$cutoffDate->format('Y-m-d')} 之前的日志文件");
  65. // 获取所有日志文件
  66. $files = File::files($this->logBackupPath);
  67. if (empty($files)) {
  68. $this->info("备份目录中没有找到任何文件");
  69. return Command::SUCCESS;
  70. }
  71. $deletedFiles = [];
  72. $keptFiles = [];
  73. $totalSize = 0;
  74. foreach ($files as $file) {
  75. $filename = $file->getFilename();
  76. $filePath = $file->getPathname();
  77. $fileModifiedTime = Carbon::createFromTimestamp($file->getMTime());
  78. $fileSize = $file->getSize();
  79. // 检查文件是否超过保留期限
  80. if ($fileModifiedTime->lt($cutoffDate)) {
  81. $deletedFiles[] = [
  82. 'name' => $filename,
  83. 'path' => $filePath,
  84. 'modified' => $fileModifiedTime->format('Y-m-d H:i:s'),
  85. 'size' => $fileSize
  86. ];
  87. $totalSize += $fileSize;
  88. // 如果不是试运行,则删除文件
  89. if (!$dryRun) {
  90. try {
  91. File::delete($filePath);
  92. $this->line("✓ 已删除: {$filename} ({$this->formatBytes($fileSize)})");
  93. } catch (\Exception $e) {
  94. $this->error("✗ 删除失败: {$filename} - {$e->getMessage()}");
  95. }
  96. } else {
  97. $this->line("○ 将删除: {$filename} ({$this->formatBytes($fileSize)}) - 修改时间: {$fileModifiedTime->format('Y-m-d H:i:s')}");
  98. }
  99. } else {
  100. $keptFiles[] = [
  101. 'name' => $filename,
  102. 'modified' => $fileModifiedTime->format('Y-m-d H:i:s'),
  103. 'size' => $fileSize
  104. ];
  105. $this->line("○ 保留: {$filename} ({$this->formatBytes($fileSize)}) - 修改时间: {$fileModifiedTime->format('Y-m-d H:i:s')}");
  106. }
  107. }
  108. // 显示清理报告
  109. $this->newLine();
  110. $this->info("=== 清理报告 ===");
  111. $this->info("总文件数: " . count($files));
  112. $this->info("删除文件数: " . count($deletedFiles));
  113. $this->info("保留文件数: " . count($keptFiles));
  114. $this->info("释放空间: " . $this->formatBytes($totalSize));
  115. if ($dryRun && !empty($deletedFiles)) {
  116. $this->newLine();
  117. $this->warn("要实际执行删除操作,请运行: php artisan ucore:clean-size-rotating-logs --days={$days}");
  118. }
  119. return Command::SUCCESS;
  120. }
  121. /**
  122. * 格式化字节大小
  123. *
  124. * @param int $bytes
  125. * @return string
  126. */
  127. protected function formatBytes(int $bytes): string
  128. {
  129. $units = ['B', 'KB', 'MB', 'GB', 'TB'];
  130. $bytes = max($bytes, 0);
  131. $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
  132. $pow = min($pow, count($units) - 1);
  133. $bytes /= pow(1024, $pow);
  134. return round($bytes, 2) . ' ' . $units[$pow];
  135. }
  136. }