如果某个项目需要上线,上线前的准备工作一定要充分,备份就是其中很重要的一个环节。备份不只是数据库的数据备份,还包括某些重要文件的备份,想象一下如果我们自己实现备份功能需要做些什么:
需要一个命令行脚本,用来将数据库或者某一些指定文件备份到某个目录下;
配置计划任务,定时地运行脚本,执行备份;
备份时会发送消息通知;
定期检查备份空间,如果空间不足,及时发送邮件通知;
配置计划任务,定期将很久之前备份文件删除。
仅仅是一个备份的功能,其实就有很多细节需要考虑,如果我们要自己实现,可能还是要费一番功夫,还会带来测试,维护等等成本。所以当项目需要某个功能的时候,一定要先去找找有没有现成的功能完备的扩展包,开发效率和维护成本会提升一大截。这一节我们来利用 spatie/laravel-backup 这个扩展包来帮助我们完成备份功能。
composer require spatie/laravel-backup
将配置文件发布出来:
php artisan vendor:publish --provider="Spatie\Backup\BackupServiceProvider"
安装过程很简单,配置文件已经发布到 config
目录中 config/backup.php
,我们暂时不修改,先来做个测试。
命令行中执行 php artisan
:
php artisan
能在命令列表中看到 bakcup
相关的命令,这些都是 spatie/laravel-backup
提供的命令:
backup:clean—— 移除所有超过配置中规定天数的旧备份;
backup:list—— 列出所有的备份;
backup:monitor—— 监控所有备份的健康情况;
backup:run—— 执行备份。
看到命令的介绍,我们知道只需要执行 php artisan backup:run
就会执行一次备份操作。
php artisan backup:run
查看输入发现,执行了数据库导出,打包文件,但是到最后报错了,这是因为 spatie/laravel-backup
每次执行的最后会发送消息通知,默认是以邮件的方式发送,我们的邮件貌似没有配置正确,为了方便我们使用 MailHog 进行测试,它是 Homestead 自带的一个组件,可以很方便地调试发送邮件。
在浏览器中访问 larabbs.test:8025 ,就可以看到 MailHog 的界面。修改 .env 中的邮件配置如下:
.env
.
.
.
MAIL_DRIVER=smtp
MAIL_HOST=127.0.0.1
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
.
.
.
再次执行 php artisan backup:run :
执行成功,打开 larabbs.test:8025 ,去 MailHog 中查看邮件。
打开收到的邮件:
可以看到关于备份的一些信息,但是好像 发件人
, 收件人
和 项目名称
信息不太对,我们调整一下配置。
调整项目名称为 LaraBBS
,同时调整发件人,假设为 admin@larabbs.test
,名字为 LaraBBS-Admin
,注意目前发件人地址和姓名需要在项目上线时替换为真实的邮件地址,且这个发件人地址是全局的,任何邮件都会默认以该发件人身份发出。
.env
APP_NAME=LaraBBS
.
.
.
MAIL_FROM_ADDRESS=admin@larabbs.test
MAIL_FROM_NAME=LaraBBS-Admin
.
.
.
收件人需要配置在 config/backup.php
中:
config/backup.php
'mail' => [
'to' => 'liyu@larabbs.test',
],
再次执行备份 php artisan backup:run
。
邮件信息正确。
我们一共执行了三次备份命令,应该会产生三个备份,我们该如何查看这些备份呢?
首先 spatie/laravel-backup
为我们提供了 backup:list
命令用来查看已存在的备份,执行一下该命令。
php artisan backup:list
这里还显示了一条备份信息,包括备份磁盘(Disk),备份距离现在的时间,备份的大小等。可以看到我们在 2 分钟前在 local 磁盘中创建了一个大小为 32.92 MB
的备份。
但是为什么执行了三次备份,却只显示了一次呢?因为备份时根据项目名称来的,项目名称就是在 .env
中配置的 APP_NAME
,前两次备份时项目叫 Laravel
,第三次备份前我们改成了LaraBBS
,所以对于现在的 LaraBBS
项目来说只有一个备份。
现在我们查找一下缓存保存的位置,打开 config/backup.php
可以看到默认配置的 disks
中只有 local
,所以备份会被保存在这里:
config/backup.php
'disks' => [
'local',
],
查看 config/filesystems.php
可以看到 local disk
的具体位置在 storage_path('app')
中,也就是 storage/app
目录。
config/filesystems.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
查看该目录:
ls storage/app/
Laravel
和 LaraBBS
这两个目录就是我们执行的三次备份存放的目录了,存放地址根据项目名称来,所以前两次存放在了 Laravel
目录中,最后一次存放在了 LaraBBS
目录中。
查看一下这两个目录中的内容:
ls storage/app/Lara*
每次备份会以日期命名,创建一个 ZIP 压缩包,可以看到三次备份的三个 ZIP 文件。现在可以把 Laravel
目录删除了,以后会使用 LaraBBS 目录保存备份。
rm -rf storage/app/Laravel/
备份文件都打包了什么,是 config/backup.php
配置文件决定的,打开配置文件,source
中配置的就是需要打包的内容。
config/backup.php
.
.
.
'source' => [
'files' => [
'include' => [
base_path(),
],
'exclude' => [
base_path('vendor'),
base_path('node_modules'),
],
'followLinks' => false,
],
'databases' => [
'mysql',
],
],
.
.
.
files—— 需要备份的文件;
include—— 包含哪些目录的文件;
exclude—— 排除哪些目录中的文件;
databases—— 需要备份的数据库。
根据配置可以知道,默认情况会备份整个项目目录,除了 vendor
和 node_modules
两个目录,以及数据库。
解压一个备份文件确认一下,注意替换
cd storage/app/LaraBBS/
unzip <your-zip-file>
会解压出两个目录 :
db-dumps —— 数据库备份文件;
home —— 文件备份。
安装一个命令行工具 tree
,方便查看树状目录结构:
sudo apt-get install tree
tree -L 4
tree
的-L
参数是显示层级,我们这里只显示 4 层。
可以看到
db-dumps目录中包含了导出的数据库
mysql-larabbs.sql,文件则是以项目所在目录的绝对路径进行的打包。遇到意外情况,需要回滚数据的时候,我们就可以解压最近的备份文件,进行恢复处理了;也方便我们复原线上项目,在本地进行
Bug` 重现及修复。
backup:monitor
命令是用来监控备份的健康状况,包括:
备份的磁盘是否可以正常连接;
备份是否使用了太多的空间;
最新的一个备份是否已经太老了,也就是很久没有执行过备份。
如果该命令的执行结果会发送通知邮件。我们运行一下该命令看看效果:
php artisan backup:monitor
当前的备份环境很健康。修改配置参数,将 storageUsedMayNotBeHigherThanMegabytes
由 5000
修改为 10
,意思是备份所占用的空间不能超过 10 M
。
config/backup.php
.
.
.
'monitorBackups' => [
[
'name' => config('app.name'),
'disks' => ['local'],
'newestBackupsShouldNotBeOlderThanDays' => 1,
'storageUsedMayNotBeHigherThanMegabytes' => 10,
],
],
.
.
.
再次运行 php artisan backup:monitor
,会提示我们环境不健康。
打开 larabbs.test:8025 ,去查看邮件。
会收到检查结果的通知邮件。你会发现无论是成功还是失败都会发送邮件,为了避免邮件发送过多,可以只让失败相关的通知发送邮件,继续修改配置:
.
.
.
'notifications' => [
'notifications' => [
\Spatie\Backup\Notifications\Notifications\BackupHasFailed::class => ['mail'],
\Spatie\Backup\Notifications\Notifications\UnhealthyBackupWasFound::class => ['mail'],
\Spatie\Backup\Notifications\Notifications\CleanupHasFailed::class => ['mail'],
\Spatie\Backup\Notifications\Notifications\BackupWasSuccessful::class => [],
\Spatie\Backup\Notifications\Notifications\HealthyBackupWasFound::class => [],
\Spatie\Backup\Notifications\Notifications\CleanupWasSuccessful::class => [],
],
.
.
.
'storageUsedMayNotBeHigherThanMegabytes' => 5000,
将通知成功相关的 notification
修改为空数组,同时将 storageUsedMayNotBeHigherThanMegabytes
修改会默认的 5000
,再次运行 php artisan backup:monitor
就不会收到成功的邮件了。
最后一个命令是清除很久之前的备份,防止因为备份过多导致的空间不足。这个清理时间同样是在配置中定义:
config/bakcup.php
'defaultStrategy' => [
'keepAllBackupsForDays' => 7,
'keepDailyBackupsForDays' => 16,
'keepWeeklyBackupsForWeeks' => 8,
'keepMonthlyBackupsForMonths' => 4,
'keepYearlyBackupsForYears' => 2,
'deleteOldestBackupsWhenUsingMoreMegabytesThan' => 5000,
],
keepAllBackupsForDays —— 保留最近 7 点内的所有备份;
keepDailyBackupsForDays——16 天以内的备份,每天会保留一份;
keepWeeklyBackupsForWeeks—— 8 周内的备份,每周会保留一份;
keepMonthlyBackupsForMonths—— 4 个月以内的备份,每个月会保留一份;
keepYearlyBackupsForYears——2 年以内的备份,每年会保留一份;
deleteOldestBackupsWhenUsingMoreMegabytesThan—— 如果备份超过了 5000 M,删除最早的备份。
我们已经了解了备份清理的逻辑和配置了,默认的备份配置其实已经考虑的很周到了,基本满足了备份的需求,可以根据真实情况作出调整。
因为我们现在没有过期的备份,所有执行 php artisan backup:clean
会看不到什么效果,我们只需要记得定时执行该命令清理备份即可。
了解了每个命令以及配置的含义,下面我们可以配置计划任务了:
app/Console/Kernel.php
.
.
.
protected function schedule(Schedule $schedule)
{
if (app()->environment('production')) {
$schedule->command('backup:run')->cron('0 */4 * * *');
$schedule->command('backup:monitor')->dailyAt('03:00');
$schedule->command('backup:clean')->dailyAt('03:10');
}
.
.
.
解释一下代码逻辑,当前环境如果是正式环境(production)时,那么:
每 4 个小时执行一次备份;
每天凌晨 3 点执行一次环境监控;
每天凌晨 3 点 10 分执行一次备份清理。