spatie/laravel-backup不是图形化“一键备份”工具,而是通过php artisan backup:run命令触发、需配置Flysystem驱动、调度任务及环境依赖的生产级自动化备份方案,不提供Web界面。

spatie/laravel-backup 不是“点一下就备份”的工具,它是一套通过 Artisan 命令驱动、可调度、带清理与通知能力的生产级备份机制。直接运行 php artisan backup:run 就能触发一次完整备份,但能否真正落地,取决于配置是否闭环、环境是否就位、调度是否生效。
backup:run 执行失败的常见原因
多数人卡在这一步,报错却找不到源头。典型现象包括:Class "GuzzleHttp\Client" not found、mysqldump: command not found、failed to open stream: Permission denied。
-
GuzzleHttp\Client缺失:Laravel 10+ 默认不带 Guzzle,必须手动执行composer require guzzlehttp/guzzle -
mysqldump不可用:PHP 进程(尤其是 CLI 模式)的$PATH中必须包含该命令;Docker 环境需在 PHP 容器内安装mariadb-client或mysql-client - 权限问题:目标磁盘路径(如
storage/app/backups)必须由 PHP 进程用户(如 www-data)可写,且不能是 Web 可直接访问的目录(如/var/www/html/storage) - 数据库连接失败:
backup:run使用的是config/database.php中定义的连接,不是 .env 里临时改的值;确认connections.mysql.host、username、password、database全部正确且可连通
如何安全配置 backup.php 的 disks 和 exclude
配置错误会导致备份体积暴增、备份失败,甚至泄露敏感文件。关键不是“全选”,而是精准控制范围。
-
destination.disks必须与config/filesystems.php中已声明的 disk 名完全一致(如['backup']),且该 disk 的root必须是绝对路径(如storage_path('app/backups')),不能用base_path('storage/app/backups')这类易错写法 -
source.files.include建议显式列出必要目录,例如:[base_path('app'), base_path('config'), base_path('routes'), base_path('resources')],避免用base_path()单独包含整个项目根目录 -
source.files.exclude至少排除:base_path('vendor')、storage_path()、base_path('node_modules')、base_path('public/storage')—— 否则备份包可能超 GB,且含大量无意义文件
为什么不能用系统 crontab 直接调 backup:run
有人图省事,在服务器上写 0 2 * * * cd /var/www && php artisan backup:run,结果日志不写、通知不发、磁盘配置失效——因为绕过了 Laravel 的完整启动流程。
- 系统 crontab 启动的 PHP 进程不加载
.env,所有config()都是默认值,数据库连接、磁盘路径、通知渠道全部错乱 - Laravel Scheduler(
schedule:run)才是唯一受信入口:它会初始化完整的应用上下文,确保config/backup.php、filesystems.php、通知驱动等全部按预期工作 - 必须只在服务器加一条 crontab:
* * * * * cd /var/www && /usr/bin/php artisan schedule:run >> /dev/null 2>&1,其余所有任务(包括backup:run和backup:clean)都应在app/Console/Kernel.php的schedule()方法中定义
大数据库(>500MB)备份超时怎么办
默认 CLI 模式下 max_execution_time=0,但实际仍可能因内存或 mysqldump 进程阻塞中断。这不是配置没生效,而是备份过程本身不可控。
- 不要依赖
set_time_limit()或修改php.ini——backup:run内部调用的是 shell 命令,PHP 超时设置对mysqldump无效 - 改用
--disable-notifications减少开销:php artisan backup:run --disable-notifications - 对超大库,建议拆分:用
DB::selectRaw()导出核心表快照,或改用原生 MySQL 事件调度器 +mysqldump脚本,绕过 Laravel 生命周期 - 务必在测试环境验证恢复流程:解压备份包 → 导入 SQL → 检查数据一致性,不能只看“生成了 zip 文件”就认为成功
真正容易被忽略的,是备份文件的可恢复性验证和磁盘空间监控。没人检查压缩包是否损坏,也没人定期删旧备份,直到某天 backup:run 因磁盘满而静默失败。











