凌晨3点,服务器突然崩了,你揉着眼睛打开备份准备恢复——结果发现:网站没备份全,数据库和用户附件全都出现了纰漏。那一刻,你才明白:备份不全,等于没备份。
做网站运维的朋友,几乎都踩过“备份不完整”的坑:备份了网站代码,却忘了完整备份数据库,恢复后网站一片空白;备份了数据库,又漏了用户上传的附件(图片、文档),导致文章配图、用户头像全部丢失;更麻烦的是,手动备份要分别操作代码、数据库、附件,耗时又容易出错,一旦遗漏某个部分,等到网站出问题需要恢复时,才发现备份等于白费。
网站备份的核心是“一体化”——把网站代码、数据库、用户附件一次性备份,自动执行、自动压缩、自动清理,既节省时间,又能确保备份完整可恢复。今天这篇实战教程,就手把手教你编写Linux网站自动备份脚本,覆盖WordPress等主流网站,包含排除无用文件、分卷压缩、快速恢复全流程。
网站备份体系架构图(一眼看懂核心流程)
[网站数据]
↓
[预处理] → 排除缓存 / 日志
↓
[压缩] → 减少体积
↓
[分卷] → 适配大文件
↓
[调度] → 定时任务自动执行
↓
[清理] → 生命周期管理
↓
[恢复] → 快速还原
一、先搞懂:网站备份的三大核心组成部分
无论你是WordPress博客、Typecho博客,还是自定义开发的网站,备份都离不开以下3个部分,少一个都不完整,恢复后都会出问题:
1. 网站代码(核心骨架)
就是网站的所有程序文件,比如WordPress的wp-content、wp-includes、wp-admin目录,以及根目录下的配置文件(如wp-config.php)。这些是网站能正常运行的“骨架”,没有代码,网站无法启动。
常见代码目录:/var/www/html(Linux默认网站根目录)、/www/wwwroot/网站域名(宝塔面板默认目录)。
2. 网站数据库(核心数据)
网站的所有动态数据都存在数据库里:文章内容、用户信息、评论、设置等。哪怕代码完整,没有数据库,网站也只是一个空壳,所有动态内容都会丢失。
常见数据库:MySQL/MariaDB(绝大多数网站使用),比如WordPress的数据库,存储着所有文章和用户数据。
3. 用户上传附件(核心资源)
这是最容易遗漏的部分,比如用户上传的文章配图、头像、下载文件、产品图片等。这些文件通常存放在代码目录下的特定文件夹(如WordPress的wp-content/uploads),体积可能很大,备份时容易被忽略。
核心结论:网站备份 = 代码备份 + 数据库备份 + 附件备份,三者缺一不可;一体化备份脚本的核心,就是把这三个部分整合起来,一键完成备份,同时避免重复备份、无效排除等隐性坑。
二、实操准备:明确备份环境与前置条件
在编写脚本前,先确认你的Linux环境和网站配置,避免后续脚本执行失败,新手可直接对照检查:
2.1 环境要求(兼容所有Linux系统)
- 系统:CentOS、Ubuntu、Debian等均可(本文以CentOS为例,Ubuntu命令略有差异,会单独标注);
- 工具:tar(压缩工具,Linux默认已安装)、mysqldump(数据库备份工具,MySQL/MariaDB默认自带);
- 权限:执行脚本的用户需拥有网站代码目录、数据库的读写权限(推荐用root用户,避免权限不足)。
2.2 提前确认的3个关键信息
| | |
|---|
| | |
| | 主机:localhost,用户名:wpuser,密码:123456,数据库名:wordpress_db |
| | /var/www/html/wordpress/wp-content/uploads |
实用提示:如果不知道数据库信息,可查看网站配置文件(如WordPress的wp-config.php),里面有明确的数据库连接信息,无需登录数据库查询。
三、核心实操:编写网站一体化自动备份脚本
这是本文的核心内容,实现以下功能:一键备份网站代码+数据库+附件、排除缓存/日志等无用文件、分卷压缩大文件、自动记录日志、备份文件按时间命名(便于区分)、失败立即退出保护,新手只需修改脚本中的配置项,即可直接使用。
3.1 完整备份脚本
#!/bin/bash
##########################################################
# Linux 网站一体化自动备份脚本(生产级优化版)
# 功能:自动备份网站代码+数据库+附件,排除无用文件,分卷压缩,日志记录,失败保护
# 适配:WordPress、Typecho等主流网站,CentOS/Ubuntu通用
# 核心关键词:网站自动备份、WordPress备份、网站备份脚本
# 修复说明:解决重复备份、排除失效、清理错误、数据一致性等5大核心问题
##########################################################
# ===================== 关键优化:失败立即退出,防止假成功 =====================
set -e
# ===================== 配置项(新手必改,对照自己的环境修改)=====================
# 1. 网站相关配置
WEB_ROOT="/var/www/html/wordpress"# 网站代码根目录(必填)
# ATTACHMENT_DIR 无需单独配置(已包含在WEB_ROOT内,避免重复备份)
BACKUP_DIR="/data/website_backup"# 备份文件存储目录(必填,建议单独分区)
# 2. 数据库相关配置
DB_HOST="localhost"# 数据库主机(默认localhost,无需修改)
DB_USER="wpuser"# 数据库用户名(必填)
DB_PASS="123456"# 数据库密码(必填)
DB_NAME="wordpress_db"# 网站对应的数据库名(必填)
# 3. 备份相关配置
BACKUP_NAME="website_backup_$(date +%Y%m%d_%H%M%S)"# 备份文件命名(按时间戳,避免重复)
# 修复:排除目录适配WordPress实际路径,避免排除失效
EXCLUDE_DIRS="wp-content/cache wp-content/upgrade logs tmp"# 排除的无用目录(缓存、日志、临时文件)
SPLIT_SIZE="200m"# 分卷压缩大小(大文件拆分,如200m/卷,可修改为500m、1g)
RETENTION_DAYS=30 # 备份文件保留天数(默认30天,自动清理过期备份)
LOG_FILE="${BACKUP_DIR}/backup.log"# 备份日志文件路径
# ===========================================================
# 1. 初始化函数(优先创建目录和日志,避免日志写入失败;增加磁盘空间检测)
init_backup() {
# 优先创建备份目录和日志文件,解决日志写入失败风险
mkdir -p ${BACKUP_DIR}
touch ${LOG_FILE}
# 优化:增强磁盘空间检测,添加阈值控制,不足1GB终止备份(生产级防护)
AVAILABLE=$(df -m ${BACKUP_DIR} | awk 'NR==2 {print $4}')
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 备份目录可用空间:${AVAILABLE}MB" >> ${LOG_FILE}
if [ ${AVAILABLE} -lt 1024 ]; then
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 错误:磁盘空间不足(小于1GB),备份终止" >> ${LOG_FILE}
exit 1
fi
# 检查tar工具是否安装
if ! command -v tar &> /dev/null; then
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 错误:tar工具未安装,备份终止" >> ${LOG_FILE}
exit 1
fi
# 检查mysqldump工具是否安装
if ! command -v mysqldump &> /dev/null; then
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 错误:mysqldump工具未安装,备份终止" >> ${LOG_FILE}
exit 1
fi
echo"[$(date '+%Y-%m-%d %H:%M:%S')] ===================== 网站一体化备份开始 =====================" >> ${LOG_FILE}
}
# 2. 数据库备份函数(导出数据库为SQL文件,修复数据一致性风险,避免密码暴露)
backup_database() {
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 开始备份数据库:${DB_NAME}" >> ${LOG_FILE}
# 修复1:用MYSQL_PWD环境变量传递密码,避免密码暴露在ps进程中
# 修复2:替换--skip-lock-tables,用更安全的参数保证数据一致性,支持存储过程/事件
MYSQL_PWD="${DB_PASS}" mysqldump -h ${DB_HOST} -u ${DB_USER} \
--single-transaction --quick --routines --events \
${DB_NAME} > ${BACKUP_DIR}/${BACKUP_NAME}_db.sql
# 检查数据库备份是否成功
if [ $? -eq 0 ]; then
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 数据库备份成功,SQL文件路径:${BACKUP_DIR}/${BACKUP_NAME}_db.sql" >> ${LOG_FILE}
else
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 错误:数据库备份失败,请检查数据库账号密码、数据库名是否正确" >> ${LOG_FILE}
exit 1
fi
}
# 3. 代码+附件备份函数(修复重复备份问题,排除无用目录生效)
backup_web_files() {
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 开始备份网站代码+附件,排除无用目录:${EXCLUDE_DIRS}" >> ${LOG_FILE}
# 构建排除目录参数(将EXCLUDE_DIRS转换为tar的--exclude格式,已适配WordPress路径)
EXCLUDE_PARAM=""
for dir in${EXCLUDE_DIRS}; do
EXCLUDE_PARAM="${EXCLUDE_PARAM} --exclude=${WEB_ROOT}/${dir}"
done
# 修复:用-C参数指定WEB_ROOT,打包当前目录,避免附件重复备份,路径更干净(恢复更方便)
tar -zcf ${BACKUP_DIR}/${BACKUP_NAME}_web.tar.gz ${EXCLUDE_PARAM} -C ${WEB_ROOT} .
# 检查代码+附件备份是否成功
if [ $? -eq 0 ]; then
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 网站代码+附件备份成功,压缩文件路径:${BACKUP_DIR}/${BACKUP_NAME}_web.tar.gz" >> ${LOG_FILE}
else
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 错误:网站代码+附件备份失败,请检查网站目录权限" >> ${LOG_FILE}
exit 1
fi
}
# 4. 分卷压缩函数(优化分卷逻辑,更专业,便于校验和恢复)
split_backup() {
# 优化:tar打包→gzip压缩→split分卷,避免断点恢复问题,更易校验
tar -cf - ${BACKUP_DIR}/${BACKUP_NAME}_db.sql ${BACKUP_DIR}/${BACKUP_NAME}_web.tar.gz | gzip | split -b ${SPLIT_SIZE} - ${BACKUP_DIR}/${BACKUP_NAME}_split_
# 检查分卷是否成功
if [ $? -eq 0 ]; then
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 分卷压缩成功,分卷大小:${SPLIT_SIZE},分卷文件路径:${BACKUP_DIR}/${BACKUP_NAME}_split_" >> ${LOG_FILE}
# 删除原始的SQL和web压缩文件(只保留分卷文件,节省空间)
rm -f ${BACKUP_DIR}/${BACKUP_NAME}_db.sql ${BACKUP_DIR}/${BACKUP_NAME}_web.tar.gz
else
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 错误:分卷压缩失败,请检查备份目录空间是否充足
可用空间:${AVAILABLE}MB,当前分卷大小:${SPLIT_SIZE}" >> ${LOG_FILE}
exit 1
fi
}
# 5. 清理过期备份函数(修复清理规则错误,确保过期备份能正常删除;修复日志误删问题)
clean_expired_backup() {
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 开始清理${RETENTION_DAYS}天前的过期备份..." >> ${LOG_FILE}
# 修复:用通配符匹配所有分卷备份,避免只能删除当前备份的问题
find ${BACKUP_DIR} -name "website_backup_*_split_*" -mtime +${RETENTION_DAYS} -delete
# 优化:不删除主日志文件,避免丢失历史备份记录;日志建议长期保留或单独做logrotate配置
# find ${BACKUP_DIR} -name "backup.log.*" -mtime +${RETENTION_DAYS} -delete
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 过期备份清理完成" >> ${LOG_FILE}
}
# 6. 备份完成提示函数
backup_complete() {
echo"[$(date '+%Y-%m-%d %H:%M:%S')] ===================== 网站一体化备份完成 =====================" >> ${LOG_FILE}
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 备份文件存储路径:${BACKUP_DIR}" >> ${LOG_FILE}
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 分卷文件前缀:${BACKUP_NAME}_split_" >> ${LOG_FILE}
echo"[$(date '+%Y-%m-%d %H:%M:%S')] 备份保留天数:${RETENTION_DAYS}天" >> ${LOG_FILE}
}
# 执行备份流程(按顺序执行所有函数)
init_backup
backup_database
backup_web_files
split_backup
clean_expired_backup
backup_complete
# 终端输出备份结果(方便手动执行时查看)
echo"✅ 网站一体化备份完成!"
echo"📁 备份文件路径:${BACKUP_DIR}"
echo"📝 备份日志路径:${LOG_FILE}"
echo"💡 分卷文件前缀:${BACKUP_NAME}_split_"
# 生产级延伸:推荐结合rsync实现增量备份+对象存储,提升备份安全性(下一篇详细讲解)
3.2 脚本使用步骤
1️⃣ 创建脚本文件
登录 Linux 服务器,执行以下命令创建脚本文件(路径可自定义):
# 进入脚本存储目录(推荐 /usr/local/scripts)
mkdir -p /usr/local/scripts
cd /usr/local/scripts
# 创建备份脚本
vim website_auto_backup.sh
2️⃣ 复制脚本内容
将上面的完整脚本复制到 vim 编辑器中:
3️⃣ 修改配置项(重点)
重新编辑脚本,修改“配置项”部分(新手必改):
vim website_auto_backup.sh
重点修改以下 5 项(其余可默认):
WEB_ROOT="你的网站代码目录"
DB_USER="你的数据库用户名"
DB_PASS="你的数据库密码"
DB_NAME="你的网站数据库名"
BACKUP_DIR="你想存储备份文件的目录"
4️⃣ 添加可执行权限
chmod +x website_auto_backup.sh
5️⃣ 测试脚本
手动执行脚本,验证是否能正常备份(首次强烈建议手动测试):
./website_auto_backup.sh
如果终端输出:
✅ 网站一体化备份完成!
说明脚本执行成功,可前往备份目录查看分卷备份文件。
6️⃣ 配置定时任务(自动执行)
让脚本每天自动执行(推荐凌晨 2 点,避开高峰):
# 编辑定时任务
crontab -e
# 添加以下内容(每天凌晨 2 点执行,并记录日志)
0 2 * * * /usr/local/scripts/website_auto_backup.sh >> /data/website_backup/backup.log 2>&1
# 查看定时任务是否生效
crontab -l
四、进阶实操:分卷压缩文件的解压与网站快速恢复
备份的核心是“可恢复”,很多新手备份后不知道如何解压分卷文件,也不知道如何快速恢复网站,这里详细讲解恢复流程,确保备份文件能正常使用。
4.1 分卷文件解压(合并分卷+解压)
分卷文件命名格式为website_backup_20260413_100000_split_aa、website_backup_20260413_100000_split_ab...,解压时需先合并分卷,再解压,步骤如下:
# 1. 进入备份文件目录
cd /data/website_backup
# 2. 合并分卷文件(替换为你的分卷文件前缀)
cat website_backup_20260413_100000_split_* > website_backup_20260413_100000.tar.gz
# 3. 解压合并后的压缩文件
tar -zxf website_backup_20260413_100000.tar.gz
# 解压后会得到两个文件:数据库SQL文件和网站代码压缩文件
# website_backup_20260413_100000_db.sql(数据库)
# website_backup_20260413_100000_web.tar.gz(代码+附件)
4.2 网站快速恢复流程(分3步,全程实操)
假设网站出现故障(如代码误删、数据库崩溃),需用备份文件恢复,步骤如下(以WordPress为例):
第一步:恢复数据库
# 1. 登录MySQL数据库
mysql -u root -p
# 2. 删除损坏的数据库(如果数据库还存在,需先删除,谨慎操作)
drop database wordpress_db;
# 3. 重新创建数据库(与备份时的数据库名一致)
create database wordpress_db character set utf8mb4 collate utf8mb4_unicode_ci;
# 4. 退出MySQL,导入备份的SQL文件(用MYSQL_PWD避免密码暴露)
exit
MYSQL_PWD="123456" mysql -u wpuser wordpress_db < website_backup_20260413_100000_db.sql
# 提示:导入成功后,数据库恢复完成
第二步:恢复网站代码+附件
# 1. 备份当前损坏的网站代码(可选,避免误操作无法回滚)
mv /var/www/html/wordpress /var/www/html/wordpress_bak
# 2. 先创建目标目录(避免目录不存在报错,同时防止文件叠加覆盖,提升恢复安全性)
mkdir -p /var/www/html/wordpress
# 3. 解压网站代码+附件压缩文件(路径更干净,恢复更便捷)
tar -zxf website_backup_20260413_100000_web.tar.gz -C /var/www/html/wordpress
# 4. 授权网站目录(避免权限异常,网站无法访问)
chown -R www:www /var/www/html/wordpress # www为网站运行用户(如nginx、apache)
chmod -R 755 /var/www/html/wordpress
第三步:验证恢复结果
- 打开浏览器,访问你的网站,查看网站是否能正常打开;
- 如果网站无法访问,检查目录权限、数据库连接配置(wp-config.php)是否正确。
注意:恢复前建议备份当前的网站代码和数据库,避免恢复失败无法回滚;如果是异地恢复,需先将分卷备份文件同步到目标服务器,再执行解压和恢复操作。特别提醒:解压前先创建目标目录(mkdir -p 目标目录),可避免目录不存在报错,同时防止文件叠加覆盖,提升恢复安全性。
五、常见问题与避坑指南(新手必看,新增修复后常见问题)
❗ 问题1:脚本执行失败,提示 mysqldump: command not found
原因:
解决方法:
# CentOS
yum install -y mysql-client
# Ubuntu
apt install -y mysql-client
如果已安装但仍报错,可查找路径并加入环境变量:
find / -name mysqldump
❗ 问题2:数据库备份失败,提示 Access denied for user
原因:
解决方法:
- 核对脚本中的
DB_USER、DB_PASS 是否正确
grantall privileges on wordpress_db.*to'wpuser'@'localhost' identified by'123456';
❗ 问题3:分卷压缩失败,提示 No space left on device
原因:
解决方法:
❗ 问题4:恢复后网站无法访问,提示“权限不足”
原因:
- Web 运行用户(如
www、nginx)没有读写权限
解决方法:
chown -R www:www /var/www/html/wordpress
chmod -R 755 /var/www/html/wordpress
👉 请替换为你自己的运行用户和网站目录
❗ 问题5:定时任务执行失败,没有生成备份文件
原因:
解决方法:
chmod +x 脚本路径
❗ 问题6:脚本执行中突然终止
原因:
set -e
解决方法:
❗ 问题7:排除目录后,缓存文件仍被备份
原因:
解决方法:
确保配置为:
wp-content/cache wp-content/upgrade logs tmp
👉 并确认路径与实际网站目录一致
六、实用技巧:提升备份安全性与效率
- 双重备份:将分卷备份文件同步到异地服务器或云存储(如阿里云OSS),避免本地磁盘损坏导致备份丢失(可结合之前的异地备份脚本实现)。
- 备份加密:如果备份文件包含敏感信息(如用户密码),可在脚本中添加加密命令(如
openssl enc -aes-256-cbc -salt -in 备份文件 -out 加密备份文件 -k 密码),提高安全性。 - 日志监控:给脚本添加告警功能(参考上一篇备份告警教程),备份失败时自动发送邮件/企业微信通知,及时发现问题。
- 定期测试恢复:每月至少执行一次恢复测试,确保备份文件可用,避免“备份了但恢复不了”的问题。
- WordPress专属优化:WordPress用户可在脚本中添加
wp cli命令,备份前清理缓存(wp cache flush),进一步减少备份文件体积。 - 生产级延伸:推荐结合
rsync实现增量备份(只备份变化的文件),搭配对象存储(如阿里云OSS、腾讯云COS),既节省磁盘空间,又提升备份安全性。
如果你觉得本文对你有帮助,欢迎点赞、推荐、转发,关注我,后续会分享更多Linux入门干货!
文 / 零距技术仓
记录每一次真实的折腾 (#^.^#)
🚀 想看到更多实用折腾技巧?
👉 先关注
💬 评论区说说你的经历或想看的内容
👍 点赞表示支持
🔁 顺手分享给也在折腾的人,让大家都少踩坑 😎