寒夏摸鱼站

Live your dream, and share your passion.

猴子都能明白的 Typecho 建站教程 #4

为了如防止手贱等意外情况发生,一个站点的备份工作是少不了的,这一章我们来实现一个定期备份功能,顺便通过邮件把备份文件发到你的邮箱里。

备份系统

Crontab 检查

我们的备份系统主要依赖于 Linux 的计划任务系统 —— crontab。crontab 依赖于服务 crond,你需要检查 crond 是否启动:

systemctl status crond

你大概能看到如下输出:

● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2023-01-08 20:11:43 CST; 1 weeks 0 days ago
 Main PID: 1138 (crond)
    Tasks: 1
   Memory: 2.0M
   CGroup: /system.slice/crond.service
           └─1138 /usr/sbin/crond -n

你需要检查几个字段:

  1. Loaded 字段里面有没有 enabled(不是 vendor preset 后面的 enabled
  2. Active 字段是否有 running

如果没有 enabled,说明 crond 并非开机启动,你需要使用如下命令使其开机启动:

sudo systemctl enable crond

如果没有 running,说明 crond 没有启动,你需要使用如下命令启动:

sudo systemctl start crond

在确保 crond 启动后,你就可以使用如下几个常用命令来操作计划任务了:

列出所有计划任务:

crontab -l

编辑计划任务:

crontab -e

实际上,crontab 计划任务表就是一个文件,所以当你编辑计划任务时,实际上进入了一个文本编辑界面。在文件中,每行代表了一个计划任务,他们看起来长这样:

* * * * * /opt/some.sh

其中前面的 5 个参数是时间参数,最后一个参数是要执行的命令,需要注意的是,所有的计划任务都是以 root 用户来执行的。

时间参数的写法是很多样的,具体有哪些你可以自己查,我们在这里就只介绍一些最简单的:

这 5 个参数从左到右分别表示分钟、小时、日期、月份和星期几。

* 表示所有,如果出现在分钟参数中,那就表示每一分钟,如果出现在小时参数中,那就是每一小时。

除了星号,时间参数还可以填写数字,如在小时参数中填写 4,表示早上 4 点(24小时制)。

除了数字,还可以填写用英文逗号隔开的数字列表,如在星期几参数中填写 1,3,5,表示星期一、星期三和星期五。

除了数字列表,还可以填写用减号隔开的数字范围,如在日期中填写 1-7,表示 1 号到 7 号。

例如如下的时间参数:

* 4 * * * 7

表示每周日(星期几参数中的 07 都代表星期日)的 4 点的 每一分钟

备份脚本的编写

对 Typecho 系统的备份基本上就只有两部分 —— 网站文件和数据库。

一般情况下,网站文件备份只需要备份 typecho/www/usr 文件夹中的文件,这里放着 Typecho 的插件、主题和上传文件,但是如果你会对 Typecho 源代码进行一定的魔改,亦或是在网站根目录下放一些 API 文件,那么你最好将整个网站都备份下来,即备份 typecho/www 文件夹下的所有内容。

数据库备份就简单多了,只有你安装了 MySQL 客户端,那么就能使用一个叫 mysqldump 的工具,把 MySQL 数据库备份成 SQL 脚本的形式。

在这里我们选择备份整个 Typecho 站点及其数据库脚本。

在 typecho 文件夹下新建一个 backup 文件夹存放备份文件,再新建一个 backup.sh 脚本文件,填写如下内容:

#!/bin/bash

time_now=$(date +%Y%m%d%H%M%S)
site_dir="{你的站点路径}"
backup_dir="{你的备份存放路径}"

bk_site_name=$backup_dir"/site.tar.gz"
bk_db_name=$backup_dir"/db.sql"
tar_name=$backup_dir"/backup_"$time_now".tar.gz"

tar -zcf $bk_site_name -C $site_dir .
mysqldump -h 127.0.0.1 -u root --password={你的 MySQL 密码} typecho > $bk_db_name

tar -zcf $tar_name -C $backup_dir site.tar.gz db.sql
rm $bk_site_name $bk_db_name

count=$(ls $backup_dir | grep .tar.gz | wc -w)
while [ $count -gt 5 ]
do
    del_name=$(ls $backup_dir -1 | grep .tar.gz | awk 'NR==1{print}')
    rm $backup_dir"/"$del_name
    count=$(ls $backup_dir | grep .tar.gz | wc -w)
done

我们讲解一下这个文件,这样你也可以自定义一部分备份的参数。先是第一部分:

time_now=$(date +%Y%m%d%H%M%S)
site_dir="{你的站点路径}"
backup_dir="{你的备份存放路径}"

bk_site_name=$backup_dir"/site.tar.gz"
bk_db_name=$backup_dir"/db.sql"
tar_name=$backup_dir"/backup_"$time_now".tar.gz"

time_now 变量通过执行 date 命令获得了备份的时间字符串,我们会用它来生成备份文件的名字。
site_dir 是你要备份的站点文件夹。
backup_dir 是备份文件存放的文件夹。
bk_site_namebk_db_name 是临时的站点备份压缩文件和临时的数据库备份文件名。
tar_name 是最终备份文件的名字与路径,你可以看见我们使用了 “backup_” + 时间字符串 + “.tar.gz” 来命名。

接下来是第二部分:

tar -zcf $bk_site_name -C $site_dir .
mysqldump -h 127.0.0.1 -u root --password={你的 MySQL 密码} typecho > $bk_db_name

tar -zcf $tar_name -C $backup_dir site.tar.gz db.sql
rm $bk_site_name $bk_db_name

第一行表示压缩打包站点目录,第二行表示导出数据库文件,第三行表示将站点压缩包和数据库文件再打包压缩成最终的备份文件,最后一行表示删除第一、二行临时生成的两个文件。

最后一部分是这样:

count=$(ls $backup_dir | grep .tar.gz | wc -w)
while [ $count -gt 5 ]
do
    del_name=$(ls $backup_dir -1 | grep .tar.gz | awk 'NR==1{print}')
    rm $backup_dir"/"$del_name
    count=$(ls $backup_dir | grep .tar.gz | wc -w)
done

这一段是控制保留的备份文件数量,在 while 那一行的数字 5 表示了我们保留最近的 5 份备份,你可以修改成其他数字。

保存 backup.sh,然后使用如下命令给它增加可执行属性:

chmod a+x backup.sh

最后我们执行一下备份,如果你能在 backup 文件夹里看见备份文件,那么我们就成功了:

./backup.sh

添加计划任务

在备份脚本编写好后,我们通过 crontab 添加一个备份任务。

因为在每周一的时候一般是访问流量最少的,且凌晨 4 点左右访问流量也更少~~(各游戏厂商.jpg)~~,所以我们设置每周一早上 4 点进行一次备份。在 crontab 任务文件中添加如下设置:

0 4 * * 1 {备份脚本的完整路径}

注:分钟参数的 0 一定要写!不要留着 *!否则系统会在 4 点的每一分钟都进行一次备份!不要问我怎么知道的!

邮件系统

配置 SMTP

在 Linux 中,可以使用 mail 命令来发送邮件,如果你的服务器没有 mail 命令,你可以运行如下命令安装:

sudo yum install mailx

因为大部分云服务厂商都关闭了 Linux 发邮件的端口,且不少邮件平台还会拒收直接从 Linux 发送的邮件,这使得我们不得不借助第三方 SMTP 服务器来发送邮件。诸如 QQ 邮箱、163 邮箱等都提供了 SMTP 服务器接口,你直接去申请启动就可以了,主要需要拿到 SMTP 服务器的地址、账号和密码,在这里不再赘述。

在得到 SMTP 相关信息后,我们用编辑器打开 /etc/mail.rc,在文件的最末尾追加如下内容:

set from={发件人}
set smtp={SMTP 服务器链接}
set nss-config-dir={本地证书目录}
set ssl-verify=ignore
set smtp-auth-user={SMTP 账号}
set smtp-auth-password={SMTP 密码}
set smtp-auth=login

一般发件人字段填写的内容和 SMTP 账号是一样的,都是一个邮箱,然后因为我们需要开启 SSL 进行邮件传输,所以 SMTP 服务器链接应该加上 smtps:// 前缀与端口后缀,如 QQ 的 SMTP 服务器是:smtp.qq.com,其 SSL 端口是 465,所以在 SMTP 服务器链接字段要填写成:smtps://smtp.qq.com:465

注:部分云主机限制了 SMTP 默认端口 25 的访问,且很多 SMTP 服务器都要求使用 SSL/TLS 进行加密传输,因此我们不考虑没有 SSL/TLS,仅使用 25 端口的情况。如上示范的是 SSL 加密传输的配置方法,且使用的端口是 465,如需 TLS 加密传输,请自行搜索。

至于本地证书目录,一般都是在 /etc/pki/nssdb,你可以检查一下你的系统有没有这个目录,如果没有那么你可以输入如下命令来查找:

sudo find / -name "cert*.db"

该命令会寻找存放在本地的证书数据库文件,其对应的文件目录就是本地证书目录。

接下来输入如下指令,测试邮件发送情况:

echo "This is a test mail" | mail -s "Test Mail" {要发送的邮箱}

如果你收到了邮件,那么 SMTP 配置就成功了。

当然,在 mail 执行的时候你可能会看见一个错误提示:

Error in certificate: Peer's certificate issuer has been marked as not trusted by the smtp-server

这意味着你的 SMTP 服务器所提供的 SSL 连接不被信任,大概率是因为你的 Linux 系统没有安装 SMTP 所提供的证书,如 QQ 所使用的 GeoTrust。但是这并不会影响你发送邮件,你也可以选择去给系统安装这个证书,具体的过程自行搜索一下即可,在此不赘述。

修改备份脚本

在邮件系统测试完毕后,我们把它集成到备份脚本里。

我们首先来学习如何在邮件中添加附件。一百来说,我们的备份文件大概在 8MB 左右,而现在很多主流邮件平台支持的附件大小在 20~50MB,所以我们不需要什么拉外链、放云盘等奇技淫巧,直接就可以把附件塞到邮件里。

我们需要先检查系统设置的单封邮件大小,执行如下命令:

postconf message_size_limit

一般情况下输出的大小为 10240000,即 10MB,这个大小其实是有点危险的,所以我们一般把这个大小改成 20 MB。用编辑器打开 /etc/postfix/main.cf,检查文件中是否定义了 message_size_limit,如果没有则在文件最后一行追加:

message_size_limit = 20480000

否则直接修改 message_size_limit 所定义的大小。最后执行如下命令重启邮箱即可:

sudo systemctl postfix restart

我们发送邮件需要的命令大概就是这么个结构:

echo "{邮件内容}" | mail -s "{邮件主题}" -a {附件路径} {目标邮箱}

所以我们回到 backup.sh,在末尾添加如下代码:

echo -e "====[ Typecho Backup System ]====\n\n A new backup has been generated" | mail -s "Typecho Backup" -a $tar_name {你的邮箱}

再次执行 backup.sh,如果你收到了一份带有备份附件的邮件,那么你就成功了!

备份恢复

我们拿到了备份文件,那么如何恢复也是我们要考虑的事情。

就上面的部分而言,我们保存了网站根目录和数据库,那么恢复的时候只需要将根目录的所有文件替换成备份即可。但是数据库恢复就有那么一点区别了:

由于我们选择将 typecho 的数据库导出,而导出文件里头并不会自带 use typecho 来选择操作的数据库,也没有 CREATE DATABASES typecho 来创建数据库(如果不存在的话)。

所以我们需要先保证 MySQL 里已经新建了 typecho 数据库,然后修改我们导出的 db.sql 文件,在第一个 SQL 语句前添加:

use typecho;

然后执行命令恢复数据库:

mysql -h 127.0.0.1 -u root -p < db.sql

输入密码后,如果命令行什么也没有输出,那么就表明数据库恢复成功了。

小结

下一章节内容待定……