本文目录导读:

在 Laravel 中,清理任务通常使用定时任务(调度任务)来实现,而不是直接用 Linux 的 crontab 写复杂脚本,Laravel 的 schedule 机制本质上还是基于 crontab,但提供了更优雅、更项目内聚的管理方式。
常见需要清理的场景
- 日志文件 -
storage/logs/laravel.log过大 - 会话文件 -
storage/framework/sessions/过期会话 - 缓存文件 - 视图缓存、数据缓存
- 临时上传文件 - 未使用的临时文件
- 数据库过期数据 - 旧日志、软删除数据等
- 活动日志/通知 - 过期的活动记录
实现方式
使用 Laravel 内置的 Schedule(推荐)
在 app/Console/Kernel.php 的 schedule 方法中定义清理任务:
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
// 清理过期会话(每天一次)
$schedule->command('session:clean')
->daily();
// 清理模型过期数据(每天凌晨2点)
$schedule->call(function () {
// 删除30天前的日志
ActivityLog::where('created_at', '<', now()->subDays(30))->delete();
// 硬删除软删除超过30天的数据
Post::onlyTrashed()
->where('deleted_at', '<', now()->subDays(30))
->forceDelete();
})->dailyAt('02:00');
// 清理临时文件(每小时)
$schedule->command('telescope:prune --hours=48')
->hourly();
// 使用 Artisan 命令清理(自定义命令)
$schedule->command('logs:clean')
->weekly()
->appendOutputTo(storage_path('logs/cleanup.log'));
}
创建自定义 Artisan 命令
如果清理逻辑复杂,建议创建独立的 Artisan 命令:
php artisan make:command CleanExpiredData
// app/Console/Commands/CleanExpiredData.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class CleanExpiredData extends Command
{
protected $signature = 'app:clean-expired-data
{--days=30 : 保留天数}
{--type=all : 清理类型(logs,sessions,db,all)}';
protected $description = '清理过期数据';
public function handle()
{
$days = $this->option('days');
$type = $this->option('type');
if ($type === 'logs' || $type === 'all') {
$this->cleanLogs($days);
}
if ($type === 'sessions' || $type === 'all') {
$this->cleanSessions();
}
if ($type === 'db' || $type === 'all') {
$this->cleanDatabase($days);
}
$this->info('清理完成!');
}
protected function cleanLogs($days)
{
// 清理 storage/logs 中的旧日志
$logFiles = glob(storage_path('logs/*.log'));
foreach ($logFiles as $file) {
if (filemtime($file) < now()->subDays($days)->timestamp) {
unlink($file);
$this->line("删除日志文件: " . basename($file));
}
}
}
protected function cleanSessions()
{
// Laravel 会自动清理 sessions,但可以手动触发
$this->call('session:clean');
}
protected function cleanDatabase($days)
{
// 清理过期记录
InactiveUser::where('last_login', '<', now()->subDays($days))->delete();
TempUpload::where('created_at', '<', now()->subDay())->delete();
}
}
然后在 Kernel.php 中调度:
$schedule->command('app:clean-expired-data --days=30 --type=all')
->dailyAt('03:00')
->onOneServer(); // 多台服务器时防止重复执行
使用队列任务(适合大批量清理)
对于大量数据清理,建议使用队列,避免阻塞主进程:
// 在 Kernel 中
$schedule->job(new \App\Jobs\CleanExpiredData(['days' => 30]))
->daily()
->withoutOverlapping(60); // 防止重复,锁60分钟
// app/Jobs/CleanExpiredData.php
public function handle()
{
// 分批删除,避免锁表
Post::where('expires_at', '<', now())
->chunkById(100, function ($posts) {
foreach ($posts as $post) {
$post->delete(); // 如果有事件监听
}
});
// 或者使用 each 分批
TempFile::where('created_at', '<', now()->subDay())
->each(function ($file) {
Storage::delete($file->path);
$file->delete();
}, 100);
}
设置 crontab(仅需一行)
在服务器上设置 crontab 即可,不需要为每个任务单独设置 cron:
# 每天执行 Laravel 调度器 * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Laravel 的 Schedule 会根据你定义的时间频率自动决定何时执行。
最佳实践建议
| 建议 | 说明 |
|---|---|
| 频率合理 | 日志每天清理,临时文件每小时,数据库过期数据每天 |
| 时间选择 | 避免高峰期,建议凌晨02:00-05:00 |
| 防止重叠 | 使用 withoutOverlapping() 防止任务重叠 |
| 监控日志 | 使用 appendOutputTo() 记录执行日志 |
| 测试优先 | 先在测试环境运行 php artisan schedule:test 测试 |
| 分批处理 | 大数据量使用 chunk 或队列,避免内存溢出 |
| 异常处理 | 在命令或 Job 中添加 try-catch 和通知 |
| 多服务器 | 使用 onOneServer() 防止多台服务器重复执行 |
示例:完整的清理策略
protected function schedule(Schedule $schedule)
{
// 每天凌晨3点清理
$schedule->command('queue:prune-failed --hours=48')
->dailyAt('03:00');
// 每周清理旧日志
$schedule->exec('find ' . storage_path('logs') . ' -name "*.log" -mtime +7 -delete')
->weekly()
->onOneServer();
// 每天清理数据库过期数据
$schedule->call(function () {
// 批量删除,记录日志
$deleted = OldRecords::where('created_at', '<', now()->subMonths(6))
->delete();
Log::info("清理了 {$deleted} 条旧记录");
})->dailyAt('04:00')
->withoutOverlapping(60)
->appendOutputTo(storage_path('logs/scheduled-clean.log'));
}
- ✅ 用 Laravel Schedule 管理清理任务(推荐)
- ✅ 创建自定义 Artisan 命令 组织复杂逻辑
- ✅ 设置 crontab 为
* * * * * php artisan schedule:run - ✅ 合理分配频率 和时间,使用
withoutOverlapping - ✅ 测试命令
php artisan schedule:test模拟执行
Laravel 的定时任务机制让清理工作变得非常整洁和可维护,而且可以充分利用 Laravel 的 ORM、事件、队列等功能来安全高效地执行。