对于任何一位站长或开发者来说,数据就是生命线。无论是网站源码被误删,还是数据库意外损坏,如果没有备份,损失往往难以挽回。手动备份虽然可行,但容易遗忘,且效率低下。本教程将手把手教你如何在一台Linux服务器上,通过脚本和定时任务,实现源码文件和数据库的自动、定时备份。整个过程无需安装额外复杂软件,纯命令行操作,安全可靠。
## 前置准备
在开始操作之前,请确保你具备以下条件:
1. **一台Linux服务器**:本文以CentOS 7/8、Ubuntu 20.04/22.04为例。你需要拥有服务器的SSH登录权限(root用户或具有sudo权限的用户)。
2. **SSH客户端**:Windows用户推荐使用Xshell、Putty或Windows Terminal;Mac或Linux用户直接使用终端。
3. **数据库信息**:如果你需要备份MySQL或MariaDB数据库,请准备好数据库的**用户名**和**密码**。通常root用户拥有全部权限,但为了安全,你也可以使用一个具有所有数据库查询权限的专用用户。
4. **确定备份路径**:
- **源码路径**:你的网站程序存放在哪里?例如 `/var/www/html` 或 `/home/wwwroot/yourdomain`。
- **备份存储路径**:你希望将备份文件存放在哪里?建议放在非系统盘,例如 `/data/backup`。如果该目录不存在,后续步骤中我们会创建。
5. **服务器时间**:确保服务器时间准确。执行 `date` 命令查看,如果时间不对,后续定时任务可能在你预期之外的时间执行。可使用 `ntpdate ntp.aliyun.com` 同步时间(需安装ntpdate)。
## 分步操作步骤
### 步骤1:创建备份存储目录并赋予权限
首先,我们需要在服务器上创建一个专门的目录来存放所有备份文件,避免与系统文件混杂。
1. 使用SSH登录你的服务器。
2. 执行以下命令创建目录(以 `/data/backup` 为例):
```bash
mkdir -p /data/backup
```
`-p` 参数的作用是:如果父目录 `/data` 不存在,则一并创建,避免报错。
3. 为了确保后续脚本有权限写入文件,我们通常将目录权限设置为755,并指定所有者。如果你的脚本使用root用户执行,可以跳过权限修改。但若使用普通用户,则需执行:
```bash
chmod 755 /data/backup
```
这条命令赋予所有者读、写、执行权限,其他用户只有读和执行权限。
### 步骤2:编写数据库备份脚本
数据库备份是整个流程的核心。我们将编写一个Shell脚本,自动导出所有数据库或指定数据库为SQL文件。
1. 在 `/data/backup` 目录下创建一个脚本文件:
```bash
vim /data/backup/backup_db.sh
```
如果vim不熟悉,可以使用 `nano /data/backup/backup_db.sh`。
2. 按下 `i` 键进入编辑模式,粘贴以下脚本内容。请务必根据你的实际情况修改变量:
```bash
#!/bin/bash
# ====== 配置区域 ======
# 数据库配置
DB_USER="root" # 数据库用户名
DB_PASSWORD="你的数据库密码" # 数据库密码
DB_HOST="localhost" # 数据库主机地址,通常为localhost
DB_NAME="--all-databases" # 备份所有数据库。若只备份单个库,改为 "your_database_name"
# 备份文件配置
BACKUP_DIR="/data/backup" # 备份文件存放目录
DATE=$(date +%Y%m%d_%H%M%S) # 获取当前时间,用于文件名,格式如:20231027_143022
# ====================
# 创建备份目录(如果不存在)
mkdir -p ${BACKUP_DIR}
# 定义备份文件名
BACKUP_FILE="${BACKUP_DIR}/db_backup_${DATE}.sql"
# 使用mysqldump命令进行备份
# 注意:mysqldump路径可能不同,可使用 which mysqldump 查找,通常为 /usr/bin/mysqldump
/usr/bin/mysqldump -u${DB_USER} -p${DB_PASSWORD} -h${DB_HOST} ${DB_NAME} > ${BACKUP_FILE} 2>/dev/null
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "数据库备份成功: ${BACKUP_FILE}"
# 压缩SQL文件以节省空间(强烈推荐)
gzip -f ${BACKUP_FILE}
echo "已压缩为: ${BACKUP_FILE}.gz"
else
echo "数据库备份失败!请检查数据库连接信息。"
exit 1
fi
# 可选:删除7天前的旧备份,防止磁盘爆满
find ${BACKUP_DIR} -name "db_backup_*.sql.gz" -type f -mtime +7 -exec rm -f {} \;
echo "已清理7天前的旧备份。"
```
3. 按下 `ESC` 键,输入 `:wq` 保存并退出(nano编辑器使用 `Ctrl+X`,然后按 `Y` 确认,再按 `Enter`)。
4. 赋予脚本执行权限:
```bash
chmod +x /data/backup/backup_db.sh
```
**脚本关键点解释**:
- `mysqldump` 是MySQL自带的备份工具,必须安装。如果没有,执行 `yum install mysql-client` 或 `apt install mysql-client`。
- `2>/dev/null` 的作用是屏蔽mysqldump的警告信息(比如密码明文警告),让输出更干净。
- `gzip -f` 强制压缩,`-f` 参数会覆盖已有同名文件。
- 最后的 `find` 命令用于自动清理,`-mtime +7` 表示修改时间超过7天的文件。你可以根据需要调整天数。
### 步骤3:编写网站源码备份脚本
源码文件同样重要,我们使用 `tar` 命令进行打包备份。
1. 创建源码备份脚本文件:
```bash
vim /data/backup/backup_site.sh
```
2. 粘贴以下内容,并修改 `SOURCE_DIR` 为你真实的网站根目录:
```bash
#!/bin/bash
# ====== 配置区域 ======
SOURCE_DIR="/var/www/html" # 你的网站源码目录,请务必修改
BACKUP_DIR="/data/backup"
DATE=$(date +%Y%m%d_%H%M%S)
# ====================
# 创建备份目录
mkdir -p ${BACKUP_DIR}
# 定义备份文件名,排除缓存等临时目录以减小体积
BACKUP_FILE="${BACKUP_DIR}/site_backup_${DATE}.tar.gz"
# 使用tar打包并压缩
# --exclude 用于排除不需要备份的目录,如缓存、日志等
tar -czf ${BACKUP_FILE} \
--exclude="cache" \
--exclude="runtime" \
--exclude="logs" \
-C / ${SOURCE_DIR#/} 2>/dev/null
# 检查打包是否成功
if [ $? -eq 0 ]; then
echo "网站源码备份成功: ${BACKUP_FILE}"
else
echo "网站源码备份失败!请检查源码目录路径。"
exit 1
fi
# 清理7天前的旧备份
find ${BACKUP_DIR} -name "site_backup_*.tar.gz" -type f -mtime +7 -exec rm -f {} \;
echo "已清理7天前的旧备份。"
```
**关于 `-C / ${SOURCE_DIR#/}` 的解释**:这一行比较关键。`-C /` 表示先切换到根目录,然后打包 `var/www/html`(去掉开头的斜杠)。这样做的好处是,解压后得到的直接是 `var/www/html` 这样的完整路径结构,而不是一堆散乱的文件。
3. 保存并赋予执行权限:
```bash
chmod +x /data/backup/backup_site.sh
```
### 步骤4:手动测试脚本是否正常运行
在设置自动执行之前,务必先手动运行一次脚本,确保没有任何错误。
1. 测试数据库备份脚本:
```bash
/data/backup/backup_db.sh
```
如果一切正常,你会看到类似输出:
```
数据库备份成功: /data/backup/db_backup_20231027_143022.sql
已压缩为: /data/backup/db_backup_20231027_143022.sql.gz
已清理7天前的旧备份。
```
2. 测试网站源码备份脚本:
```bash
/data/backup/backup_site.sh
```
成功输出:
```
网站源码备份成功: /data/backup/site_backup_20231027_143022.tar.gz
已清理7天前的旧备份。
```
3. 检查备份文件是否真实生成:
```bash
ls -lh /data/backup/
```
你应该能看到 `.sql.gz` 和 `.tar.gz` 文件。如果文件大小为0KB,说明备份失败,需要检查路径或权限。
### 步骤5:设置定时任务(Crontab)
脚本已经就绪,现在通过Linux的定时任务服务 `crontab` 让它们每天自动运行。
1. 编辑当前用户的crontab文件(推荐使用root用户,以确保有权限访问所有文件):
```bash
crontab -e
```
如果你是第一次运行,系统会提示你选择编辑器。选择 `vim` 或 `nano` 均可。
2. 在文件末尾添加以下两行内容(每行代表一个定时任务):
```bash
# 每天凌晨2点30分备份数据库
30 2 * * * /bin/bash /data/backup/backup_db.sh >> /data/backup/backup.log 2>&1
# 每天凌晨3点整备份网站源码
0 3 * * * /bin/bash /data/backup/backup_site.sh >> /data/backup/backup.log 2>&1
```
**Crontab时间格式详解**(从左到右):
- 分钟 (0-59)
- 小时 (0-23)
- 日 (1-31)
- 月 (1-12)
- 星期 (0-7, 0和7都代表周日)
- `*` 表示任意值。
- 所以 `30 2 * * *` 代表“每天凌晨2点30分”。
- `>> /data/backup/backup.log 2>&1` 表示将脚本执行的标准输出和错误输出都追加到 `backup.log` 文件中,方便日后查看执行情况。
3. 保存并退出。crontab会自动安装这个新任务。
4. 检查定时任务是否成功安装:
```bash
crontab -l
```
你应该能看到刚刚添加的两行内容。
### 步骤6:验证定时任务是否生效
为了确保定时任务真的会执行,我们可以通过查看日志文件来确认。
1. 等待设定的时间点过去,或者为了快速测试,你可以临时修改crontab时间(例如改为当前时间后2分钟),但测试完记得改回来。更稳妥的方法是手动检查日志:
```bash
# 查看日志文件末尾
tail -f /data/backup/backup.log
```
如果脚本成功执行,你会看到类似下面的日志:
```
数据库备份成功: /data/backup/db_backup_20231028_023001.sql.gz
已清理7天前的旧备份。
网站源码备份成功: /data/backup/site_backup_20231028_030002.tar.gz
已清理7天前的旧备份。
```
2. 你也可以检查 `cron` 服务本身的日志(不同系统路径不同):
- CentOS/RHEL:`grep CRON /var/log/cron`
- Ubuntu/Debian:`grep CRON /var/log/syslog`
如果看到类似 `(root) CMD (/bin/bash /data/backup/backup_db.sh ...)` 的记录,说明定时任务已经被触发。
## 常见问题
**Q1:执行脚本时提示 “mysqldump: command not found”**
**A**:这是因为系统没有安装MySQL客户端工具。执行以下命令安装:
- CentOS:`yum install mysql -y`
- Ubuntu:`apt-get install mysql-client -y`
安装后再次运行脚本即可。
**Q2:备份生成的SQL文件大小为0KB**
**A**:这通常是因为数据库用户名或密码错误,导致mysqldump连接失败。请检查 `backup_db.sh` 中的 `DB_USER` 和 `DB_PASSWORD` 是否完全正确。另外,确认数据库服务是否正在运行:`systemctl status mysqld` 或 `systemctl status mysql`。
**Q3:定时任务到时间了却没有执行**
**A**:请按以下顺序排查:
1. 检查cron服务是否在运行:`systemctl status crond`(CentOS)或 `systemctl status cron`(Ubuntu)。如果未运行,执行 `systemctl start crond` 并设置开机自启 `systemctl enable crond`。
2. 检查crontab文件是否保存正确:`crontab -l` 查看输出。
3. 检查脚本是否有执行权限:`ls -l /data/backup/backup_db.sh`,确认有 `x` 权限。
4. 检查脚本中是否使用了绝对路径。在crontab中,环境变量可能不完整,所以脚本内部的所有命令(如 `mysqldump`、`tar`、`gzip`)最好都使用绝对路径(如 `/usr/bin/mysqldump`)。
**Q4:备份文件越来越大,磁盘空间不足**
**A**:脚本中已经包含了自动清理7天前备份的功能。你可以通过修改 `find` 命令中的 `+7` 来调整保留天数,例如改为 `+3` 只保留3天。此外,可以考虑将备份文件远程传输到其他服务器或对象存储(如OSS、S3),但这超出了本教程范围。
**Q5:我想备份单个数据库,而不是所有数据库**
**A**:修改 `backup_db.sh` 中的 `DB_NAME` 变量。将 `--all-databases` 改为你具体的数据库名称,例如 `DB_NAME="wordpress"`。注意,如果只备份单个库,`--all-databases` 这个参数就不能用了。
## 收尾总结
通过以上六个步骤,你已经成功在服务器上搭建了一套完整的自动备份系统。现在,你的网站源码和数据库会在每天凌晨的指定时间自动打包、压缩,并存放在 `/data/backup` 目录下,同时系统会自动清理超过7天的旧备份,避免了磁盘被历史备份文件填满的风险。
这套方案的核心优势在于:**完全免费、不依赖第三方服务、纯命令行操作、资源消耗极低**。无论你的服务器是几百元的虚拟主机还是高性能云服务器,这套脚本都能稳定运行。唯一需要你做的,就是偶尔登录服务器,检查一下 `/data/backup/backup.log` 文件,确保备份任务每天都在正常工作。养成这个习惯,你的数据安全就有了最坚实的保障。