一、要做什么
先不真正上传。
先把“准备备份”这件事做好。
原因很简单:
如果本地结构本身是乱的,那么上传到对象存储以后,只会把混乱复制一份。
现在只做这些事:
- 再检查本地目录是否干净
- 确认哪些目录必须备份
- 确认哪些目录不必优先备份
- 给每个来源建立固定的备份思路
- 生成一个本地打包脚本
- 以后对象存储接入时,直接用这个结构即可
结束后,不会真正上传到 Cloudflare R2。
但会把:
- 该备份什么
- 不该备份什么
- 如何打包
- 打包后长什么样
全部固定下来。
二、先确认当前项目结构
执行:
tree -L 3 /srv/policybot
正常情况下,你应该已经有类似结构:
/srv/policybot
├── crawler
├── data
│ ├── ndrc
│ └── miit
├── export
└── logs
如果目前只有一个来源,那就会看到:
/srv/policybot
├── crawler
├── data
│ └── ndrc
├── export
└── logs
三、哪些目录必须备份
真正要备份的,是以后很难重新恢复的内容。
必须备份
1. 原始 html
/srv/policybot/data/ndrc/raw_html
原因:
- 这是原始网页
- 后续如果想重新提取字段,可以从 html 重跑
- 一旦源网站改版或删页面,html 就很难补回
2. 提取后的 txt
/srv/policybot/data/ndrc/text
原因:
- 这是后续做关键词、主题分析、分类的基础文本
- 可以直接给 Python / 机器学习 / 向量化使用
3. 索引文件
/srv/policybot/data/ndrc/index/policy_index.csv
/srv/policybot/data/ndrc/index/url_index.txt
原因:
policy_index.csv决定你如何找到每条文件url_index.txt决定增量更新是否会重复
4. 清洗导出文件
/srv/policybot/export/ndrc
原因:
- 这里面是你已经做过筛选、标记、分类的结果
- 这些结果可以重做,但如果规则很多,重做会花时间
四、哪些目录可以暂时不优先备份
1. logs
/srv/policybot/logs
日志有用,但不是最高优先级。
原因:
- 日志主要用于排错
- 丢了日志不会导致原始数据丢失
- 真正重要的是 html、txt、索引、导出结果
2. crawler
/srv/policybot/crawler
脚本也重要,但脚本通常可以:
- 从 Git
- 从博客
- 从本地文档
- 从你自己的笔记
重新恢复。
如果对象存储空间或操作数有限,优先级仍然排在数据后面。
当然,如果空间足够,后面也可以一起备份。
五、备份时不应该怎么做
不要把整个 /srv/policybot 目录直接随便一股脑同步。
原因:
- 里面有你不一定需要的内容
- 以后临时测试文件也会混进去
- 恢复时不够清晰
- 不利于按来源、按月份检查
正确做法是:
按来源、按目录、有选择地备份。
例如:
data/ndrc/raw_htmldata/ndrc/textdata/ndrc/indexexport/ndrc
以后新增 miit,就再加:
data/miit/raw_htmldata/miit/textdata/miit/indexexport/miit
六、为什么现在就要建立打包规则
你未来数据只会越来越多。
一开始如果不固定规则,后面就会出现这些问题:
- 不知道哪个月有没有备份
- 不知道哪个来源备份到了哪里
- 不知道某个目录是不是完整同步过
- 恢复时只能整盘恢复,非常低效
所以现在就先固定一个最简单的原则:
先按来源打包,再按目录打包。
例如 ndrc 这个来源,以后至少分四类包:
raw_htmltextindexexport
七、先创建本地备份目录
即使还没接 R2,也先在本地留一个打包目录。
执行:
mkdir -p /srv/policybot/backup
mkdir -p /srv/policybot/backup/ndrc
查看:
tree -L 2 /srv/policybot/backup
正常应看到:
/srv/policybot/backup
└── ndrc
以后这个目录专门放“准备上传到对象存储的压缩包”。
八、先手动打一个最小测试包
先测试一个最小包,确认打包没有问题。
执行:
tar -czf /srv/policybot/backup/ndrc/index_backup.tar.gz -C /srv/policybot/data/ndrc index
这条命令的意思是:
- 把
data/ndrc/index打包 - 压缩成
index_backup.tar.gz
查看:
ls -lh /srv/policybot/backup/ndrc
正常会看到类似:
-rw-r--r-- 1 root root 4.0K Mar 14 12:00 index_backup.tar.gz
九、检查压缩包内容
不要只看压缩包存在。
要确认里面内容正确。
执行:
tar -tzf /srv/policybot/backup/ndrc/index_backup.tar.gz
正常会看到类似:
index/
index/policy_index.csv
index/url_index.txt
这说明:
- 打包结构正确
- 以后恢复时不会乱
十、再打 html 和 txt 包
继续执行:
tar -czf /srv/policybot/backup/ndrc/raw_html_backup.tar.gz -C /srv/policybot/data/ndrc raw_html
tar -czf /srv/policybot/backup/ndrc/text_backup.tar.gz -C /srv/policybot/data/ndrc text
查看:
ls -lh /srv/policybot/backup/ndrc
现在应该能看到:
index_backup.tar.gz
raw_html_backup.tar.gz
text_backup.tar.gz
如果已经做过清洗导出,再加一个导出包:
tar -czf /srv/policybot/backup/ndrc/export_backup.tar.gz -C /srv/policybot/export ndrc
十一、检查压缩包是否可读
不要只打包,不验证。
执行:
tar -tzf /srv/policybot/backup/ndrc/raw_html_backup.tar.gz | head
tar -tzf /srv/policybot/backup/ndrc/text_backup.tar.gz | head
正常会看到类似:
raw_html/
raw_html/2024/
raw_html/2024/03/
raw_html/2024/03/2024-03-18_xxxxx.html
以及:
text/
text/2024/
text/2024/03/
text/2024/03/2024-03-18_xxxxx.txt
这一步确认:
- 归档目录层级被正确保留
- 以后恢复时路径会清楚
十二、把打包过程写成脚本
不要每次手工敲命令。
直接写成脚本。
执行:
cat > /srv/policybot/crawler/backup_ndrc.sh <<'SH'
#!/bin/bash
set -e
BACKUP_DIR="/srv/policybot/backup/ndrc"
DATA_DIR="/srv/policybot/data/ndrc"
EXPORT_DIR="/srv/policybot/export"
mkdir -p "$BACKUP_DIR"
tar -czf "$BACKUP_DIR/index_backup.tar.gz" -C "$DATA_DIR" index
tar -czf "$BACKUP_DIR/raw_html_backup.tar.gz" -C "$DATA_DIR" raw_html
tar -czf "$BACKUP_DIR/text_backup.tar.gz" -C "$DATA_DIR" text
if [ -d "$EXPORT_DIR/ndrc" ]; then
tar -czf "$BACKUP_DIR/export_backup.tar.gz" -C "$EXPORT_DIR" ndrc
fi
echo "backup done"
SH
赋予执行权限:
chmod +x /srv/policybot/crawler/backup_ndrc.sh
运行:
/srv/policybot/crawler/backup_ndrc.sh
正常输出:
backup done
十三、检查打包结果
执行:
ls -lh /srv/policybot/backup/ndrc
如果目录中有:
index_backup.tar.gz
raw_html_backup.tar.gz
text_backup.tar.gz
说明脚本已经能用。
如果此前已经有导出文件,还会看到:
export_backup.tar.gz
十四、以后新增第二个来源时怎么备份
逻辑完全一样。
例如新增 miit 后,先建备份目录:
mkdir -p /srv/policybot/backup/miit
然后打包:
tar -czf /srv/policybot/backup/miit/index_backup.tar.gz -C /srv/policybot/data/miit index
tar -czf /srv/policybot/backup/miit/raw_html_backup.tar.gz -C /srv/policybot/data/miit raw_html
tar -czf /srv/policybot/backup/miit/text_backup.tar.gz -C /srv/policybot/data/miit text
如果有导出:
tar -czf /srv/policybot/backup/miit/export_backup.tar.gz -C /srv/policybot/export miit
也就是说:
每个来源各自一套备份目录,各自一套压缩包。
不要把所有来源全混进一个大包。
十五、以后接入对象存储时,上传什么
等以后真正接 R2 时,你上传的不是整个项目目录,而是:
/srv/policybot/backup/ndrc/index_backup.tar.gz
/srv/policybot/backup/ndrc/raw_html_backup.tar.gz
/srv/policybot/backup/ndrc/text_backup.tar.gz
/srv/policybot/backup/ndrc/export_backup.tar.gz
以及别的来源对应的备份包。
这样好处很明显:
- 本地目录清晰
- 上传目标清晰
- 对象存储里不会一团乱
- 恢复时只取需要的包
- 某个来源损坏时只恢复那个来源,不影响别的
十六、完成后的状态
完成后,项目目录会多出:
/srv/policybot
├── backup
│ └── ndrc
│ ├── index_backup.tar.gz
│ ├── raw_html_backup.tar.gz
│ ├── text_backup.tar.gz
│ └── export_backup.tar.gz (如果有导出)
并且 crawler 目录中新增:
/srv/policybot/crawler/backup_ndrc.sh
到这里,已经完成了:
- 本地原始数据整理
- 原始数据归档
- 清洗结果导出
- 备份目录建立
- 打包脚本建立
也就是说:
即使此刻还没有接 Cloudflare R2,本地备份体系也已经固定好了。
后面一旦接对象存储,只需要上传这些打包好的文件即可。