51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

用Shell脚本实现Halo博客系统全站定时备份,并将备份文件发送至邮箱存储

前言 {#%E5%89%8D%E8%A8%80}

当然,首推halo 应用市场 是有付费的备份插件,如果不想买付费插件,可以用我这个实现,邮箱那么大的容量为什么不用(比如QQ邮箱早期很多人都有无限容量)

脚本实现思路:

  • 编写脚本,将halo数据库导出为.sql文件,并与.halo目录一起打包成打包成压缩文件,以附件的方式发送到自己的邮箱

  • 但是一个Halo全栈数据包括.halo目录下的文件数据库,其文件大小远远超过邮箱附件大小最大限制

  • 这里处理完毕后是以压缩分卷的形式存在的,也就是将一个压缩文件打包成多个压缩分卷,每一个压缩分卷以附件的形式用一个邮件发送出去,因为SMTP发送邮件对附件大小有限制,一般是最大8M,所以后面设置附件大小也就是每个压缩分卷大小为8M

最终实现结果:

  • 邮箱会收到很多封邮件,最后都下载下来,手动合并成一个压缩文件就可,唯一标识是备份时刻

  • 结合cron设置定时执行该脚本,实现Halo博客系统全站定时备份,并备份文件发送给邮箱存储

需要安装的依赖 {#%E9%9C%80%E8%A6%81%E5%AE%89%E8%A3%85%E7%9A%84%E4%BE%9D%E8%B5%96}

  • 与邮箱管理的有关的软件包 msmtp 和 mutt

  • 与定时任务有关的软件包

安装msmtp 和 mutt {#%E5%AE%89%E8%A3%85msmtp-%E5%92%8C-mutt}

sudo apt-get install msmtp mutt -y

sudo apt install msmtp ca-certificates

配置msmtp 和 mutt {#%E9%85%8D%E7%BD%AEmsmtp-%E5%92%8C-mutt}

新建专门用于备份的用户 {#%E6%96%B0%E5%BB%BA%E4%B8%93%E9%97%A8%E7%94%A8%E4%BA%8E%E5%A4%87%E4%BB%BD%E7%9A%84%E7%94%A8%E6%88%B7}

建议新建一个用户专门用来操作备份,主要是为了防止发生意外操作,因为后面配置的脚本中有删除操作,如果你不小心填错了备份目录,root用户误删除比较危险

创建用户名

useradd -m onlybackup

给用户设置密码

passwd onlybackup

切换到onlybackup

su onlybackup

切换到onlybackup家目录

cd /home/onlybackup

配置mutt和msmtp {#%E9%85%8D%E7%BD%AEmutt%E5%92%8Cmsmtp}

nano .muttrc

填入如下内容,注释部分替换成自己的

                set sendmail="/usr/bin/msmtp"
set use_from=yes
# 发件人名字
set realname="Logdict Backup Service"
# 发件人地址
set from=xxx.com 
set envelope_from=yes
`set charset="utf-8"
set send_charset="utf-8"
set content_type = "text/html;charset=utf-8"
`

nano .msmtprc

填入如下内容, 注释部分替换成自己的

              
                # Set default values for all following accounts.
defaults
auth           on
# 是否开启tls
tls            on
# 如果是tls_starttls on
tls_starttls  off 
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        ~/.msmtp.log

account        alimail


填入发件箱服务商SMTP地址
==============



host           smtp.qiye.aliyun.com


SMTP端口号
=======



port           465


邮箱账号
====



from           xx.com


邮箱账号
====



user           xx.com


邮箱账号密码或授权码
==========



password     xx


Set a default account
=====================


`account default : alimail
`

赋予执行权限

chmod 600 msmtprc

发送测试邮箱

echo "Hello, this is a test email." | msmtp -a default xxxxx@qq.com

如果没错误就是代表成功了,检查收件邮箱收件箱,或者发件邮箱的已发送邮件,看是否有邮件,一般发件邮箱是发不出去的,因为被识别成了垃圾邮件退信了

编写脚本 {#%E7%BC%96%E5%86%99%E8%84%9A%E6%9C%AC}

创建备份目录

mkdir -p /home/onlybackup/halo_backup

把标有手动设置新注释部分,换成自己的即可,然后创建脚本nano halo_backup.sh

主要配置下面

  • 备份存储的位置

  • .halo2文件夹的路径

  • 数据库信息,用户名和密码

  • 接受备份的邮箱

              
                #!/bin/bash
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin
export PATH
export LANG=C

----------------------------------手动配置部分-----------------------------------------------------
=============================================================================================



halo_bak_name="halo_backup"         # 生成的备份文件名
backup_path="/home/onlybackup/halo_backup" # 备份存储路径
halo2_path="/home/halo/.halo2"      # .halo2的路径
database="halo"                     # 数据库名
u="xxxxxxxxx"                       # 数据库用户
p="xxxxxxxxx"                       # 数据库密码(建议使用环境变量)
mail_address="xxxxxxxxxqq.com"     # 接受备份的邮箱


----------------------------------清理备份文件夹-----------------------------------------------------
==============================================================================================



echo "开始清理备份文件夹"
rm -rf "${backup_path}"/\* \|\| { echo "清理备份文件夹失败!"; exit 1; }


清理mutt临时文件
==========



cat /dev/null \> \~/sent
echo "清理备份文件夹结束"


----------------------------------自动创建目录-----------------------------------------------------
=============================================================================================



mysql_backup_path="${backup_path}/mysql_bak"
halo_backup_path="${backup_path}/halo_bak"
datetime=$(date +%F_%H%M)


创建备份目录
======



if ! mkdir -p "$mysql_backup_path" "$halo_backup_path"; then
echo "创建备份目录失败!"
exit 1
fi


----------------------------------配置校验-----------------------------------------------------
===========================================================================================



检查邮件地址是否为空
==========



if \[ -z "$mail_address" \]; then
echo "邮件地址不能为空,请设置接收邮件地址。"
exit 1
fi


----------------------------------备份数据库-----------------------------------------------------
============================================================================================



halo_mysql_bak_name="halo_sql_bak-${datetime}.sql.gz"
echo "开始导出SQL文件并压缩"
if ! /bin/mysqldump -u "$u" -p"$p" -h 127.0.0.1 -R --opt "$database" \| gzip \> "${mysql_backup_path}/${halo_mysql_bak_name}"; then
echo "数据库备份失败,请检查 mysqldump 命令或数据库连接"
exit 1
fi
echo "数据库导出并压缩结束"


----------------------------------.halo2目录与SQL文件合并压缩-----------------------------------------------------
=========================================================================================================



echo "开始分卷压缩 .halo2 与 SQL 文件"
if ! tar -jpcf - "$halo2_path" "${mysql_backup_path}/${halo_mysql_bak_name}" \| split -b 8m --numeric-suffixes=1 - "${halo_backup_path}/${halo_bak_name}-${datetime}.tar.bz2.part-"; then
echo "分卷压缩失败,请检查 tar 和 split 命令"
exit 1
fi
echo "分卷压缩结束"


计算分卷数量
======



total_parts=$(ls ${halo_backup_path}/${halo_bak_name}-${datetime}.tar.bz2.part\* \| wc -l)
echo "本次总共分卷数: $total_parts"


----------------------------------发送备份文件-----------------------------------------------------
=============================================================================================



send_backup_email() {
local file="$1"
local total_parts="$2"
local mail_address="$3"
local file_name
file_name=$(basename "$file")
local subject="$file_name"
local content="本次备份共计 ${total_parts} 卷; 当前第 ${file_name} 卷"


    # 发送邮件
    if ! printf "%s" "$content" | mutt -s "$subject" "$mail_address" -a "$file"; then
        echo "发送文件 $file 失败,请检查邮件配置或连接"
        return 1
    fi
    echo "发送: $file_name to $mail_address"




}


遍历并发送所有分卷
=========



for file in ${halo_backup_path}/\*; do
if \[ -f "$file" \]; then
send_backup_email "$file" "$total_parts" "$mail_address" \|\| { echo "发送失败: $file"; exit 1; }
fi
done
echo "全部发送完毕"


----------------------------------清理工作-----------------------------------------------------
===========================================================================================



清理mutt临时文件
==========



cat /dev/null \> \~/sent


清理备份文件夹
=======



echo "开始清理备份文件夹"
rm -rf "${backup_path}"/\* \|\| { echo "清理备份文件夹失败!"; exit 1; }
echo "清理备份文件夹结束"


----------------------------------结束脚本-----------------------------------------------------
===========================================================================================



echo "执行结束"


              </code>
            </pre>



 
<br />



 
脚本测试 {#%E8%84%9A%E6%9C%AC%E6%B5%8B%E8%AF%95}
--------------------------------------------


 
上面编写脚本完毕后,可以运行 ` sh halo_backup.sh `

 
以下是正确运行后的界面输出

 
![](http://static.51tbox.com/static/2024-12-09/col/d04cb1f643c98ecd6959cd4eb042afd6/7a3628e7dce344299bb0c5b7a7f7a7f0.png.jpg)

 
收件邮箱会收到邮件,如图

 
![](http://static.51tbox.com/static/2024-12-09/col/d04cb1f643c98ecd6959cd4eb042afd6/7214a63566614694b3a287d5ed933ef7.png.jpg)

 
合并收到的附件 {#%E5%90%88%E5%B9%B6%E6%94%B6%E5%88%B0%E7%9A%84%E9%99%84%E4%BB%B6}
--------------------------------------------------------------------------


 
![](http://static.51tbox.com/static/2024-12-09/col/d04cb1f643c98ecd6959cd4eb042afd6/1bcf9bec255141aa8c6324927b8ce0b9.png.jpg)

 
关于邮件附件名和标题名的说明

 
halo_bak_archive-2024-11-25_0844.tar.bz2.part-18

 
表示备份于2024-11-25_0844,时间也是唯一标识;part-18 表示第18卷

 
邮件内容里会告诉你一共有多少卷

 
根据备份时间是唯一标识和part是第几卷,把所有的邮件下载下来放到一个文件夹,如图

 
![](http://static.51tbox.com/static/2024-12-09/col/d04cb1f643c98ecd6959cd4eb042afd6/33dfc5b4850c4b9491ba394d94595d89.png.jpg)

 
Windows CMD命令执行,最简单的方法,在地址栏输入cmd回车进入命令行

 
执行如下命令将所有分卷合并成一个压缩文件

 
` copy /b halo_bak_archive-2024-11-24_1400.tar.bz2.part-* halo_bak_archive-2024-11-24_1400.tar.bz2 `

 
如果你一个文件夹下只有一个时间的备份

 
直接运行 ` copy /b * 合并后文件名.tar.bz2 ` 也可

 
合并后的文件直接Windows一般的压缩文件就可以解压缩了,里面分别嵌套了好几层压缩文件需要解压(这个是我脚本没写好),解压出来就是.halo2目录和sql文件的备份了,到时候恢复的时候上传.halo2目录和恢复数据库即可

 
配置定时任务 {#%E9%85%8D%E7%BD%AE%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1}
----------------------------------------------------------------


 
安装定时任务软件包(一般debian都内置)

 
` apt-get install cron `

 
配置隔三天备份一次

 
创建定时任务

 
` crontab -e `

 
输入

 
` 0 5 */3 * * sh /home/onlybackup/halo_backup.sh `

 
定时任务怎么设置可以参考 https://www.runoob.com/w3cnote/linux-crontab-tasks.html

 
设置好后有一个验证定时任务执行时间的工具 https://tool.lu/crontab/

 
<br />



 
巧用邮箱收信规则 {#%E5%B7%A7%E7%94%A8%E9%82%AE%E7%AE%B1%E6%94%B6%E4%BF%A1%E8%A7%84%E5%88%99}
------------------------------------------------------------------------------------


 
![](http://static.51tbox.com/static/2024-12-09/col/d04cb1f643c98ecd6959cd4eb042afd6/a183ce097de848f3ad164f58985bf123.png.jpg)

 
邮箱一般都带有收信规则,所以我设置了如图所示,当收到的邮箱主题包含xxxxx,自动归档到博客备份文件夹

 
<br />



 
后记 {#%E5%90%8E%E8%AE%B0}
------------------------


 
如果嫌麻烦的(其实就装几个软件包,改几处)直接买官方的备份插件,另外这个其实编成halo插件更简单,不过我懒得看文档

 
当然你的站点如果几G十几G那算了,还是用官方的插件吧,估计有的邮箱会限制一天发送多少带有附件的邮件

 
对于附件那个大小我是设置8M,如果你的邮箱服务商对SMTP附件大小更大,可以自行修改,因为我的邮箱是15M,官方建议是8M,因为经过编码后会溢出到\>8M

 
halo如果你不在本站存储图片等数据,其实容量占大头的是backup备份目录(尤其是你执行过备份)和插件plugins插件目录,以及themes主题目录,这些目录完全可以不用备份,插件只读取所有插件的名称输出存储成附件即可,主题目录同理;到时候自己找对应版本插件下载手动传上去即可。这部分脚本可以自己改一下

赞(0)
未经允许不得转载:工具盒子 » 用Shell脚本实现Halo博客系统全站定时备份,并将备份文件发送至邮箱存储