Ghost 实现自动化备份
0x0 前言
2024.06.26 已更新
前几天在折腾主机时候,不小心把环境搞乱了,无奈最后联系腾讯云工程师挽救,虽然最终能进入SSH备份数据,但 sudo
无法使用,无奈重装系统。这次事件发生后觉得有必要做个自动化备份。摆在以前的 WordPress
平台可以实现各种插件备份方法。
对于 Ghost
平台备份也不算复杂,直接备份数据库和平台数据就行了,至于实现就可以使用 shell
脚本实现。
0x1 数据库备份
新建 mysql 备份用户,用于只备份于 Ghost
数据,严格控制对应的权限:
mysql -uroot -p
CREATE USER 'backup'@'localhost' IDENTIFIED BY '你的密码';
GRANT ALL ON iiong.* TO 'backup'@'localhost';
FLUSH PRIVILEGES;
quit;
注意
iiong
是你 Ghost 指定的数据,不清楚可以查看Ghost/config.production.json
文件
扩展:
SHOW GRANTS FOR 'backup'@'localhost'; # 查看权限列表
REVOKE ALL ON *.* FROM 'backup'@'localhost'; # 删除所有权限操作
创建 .my.cnf
文件
echo '[client]
user=backup
password="你的密码"' >> ~/.my.cnf
赋值权限:
sudo chmod 600 ~/.my.cnf
执行下面命令是否正常备份sql文件:
mysqldump iiong > ~/iiong.sql
因为数据库版本问题如果导出控制台报 “mysqldump: Error: 'Access denied; you need (at least one of) the PROCESS privilege(s) for this operation' when trying to dump tablespaces” 错误直接添加参数:
mysqldump iiong > ~/iiong.sql --no-tablespaces
如果没有异常说明可以继续下一步。
0x3 编写脚本
为了方便将上面备份的 sql
文件进行压缩和日期:
mysqldump iiong | gzip > ~/iiong-$(date +%Y%m%d).sql.gz
然后再备份 Ghost
目录下的 content
文件夹,这个文件夹下包含博客的图片和一些关键配置文件,也包括类似数据库文件:
tar -zcvf ~/content-$(date +%Y%m%d).tar.gz /var/www/ghost/content/
整合脚本 backup.sh
,在用户根目录下新建脚本:
cd ~
mkdir backup backup/ghost
cd backup
#!/bin/bash
. ~/.bashrc
alipanBackupPath="/Ghost/"
now=$(date +'%Y-%m-%d_%H-%M')
database="$HOME/backup/ghost/iiong-$now.sql.gz"
ghostdata="$HOME/backup/ghost/content-$now.tar.gz"
echo "保存数据库文件到备份文件夹"
mysqldump iiong --no-tablespaces | gzip > $database
echo "备份 Ghost 数据"
tar -zcvf $ghostdata --absolute-names /var/www/i95.me/content/ > /dev/null
echo "备份Ghost和数据库文件到阿里云盘"
aliyunpan upload $ghostdata $database $alipanBackupPath
如果提示上传超时,查看
content-xxx.tar.gz
容量很大,需要修改-t
参数,单位为秒。
保存成功后设置脚本权限:
sudo chmod a+x ./backup.sh
根据下列文档安装阿里云盘工具命令:aliyunpan
请到阿里云盘网页版登录后任意界面浏览器调出开发者工具(F12
或者 command+option+i
)在 Application
窗口下的 Local Storage
菜单中右边窗口里面的 token
对象中的 refresh_token
复制它的值就行了,具体截图可以参考:更新 token 说明,然后写入环境:
aliyunpan login
0x4 添加任务
crontab -e
# 在任务表添加下列任务
0 0 * * * /usr/bin/bash /home/ubuntu/backup/backup.sh # 每天 0 点执行
*/5 * * * * /usr/bin/bash /home/ubuntu/backup/backup.sh # 每5分钟执行一次 可以拿这个测试
效果如下:
0x5 通知
大概使用几天后发现莫名其妙不备份了,查看一看是阿里云盘的 token
失效了,所以花了时间写了个通知脚本,利用脚本执行 shell
在成功或者失败回调进行通知,通知方式我是使用PushDeer
,胜在稳定吧,如果需要可以在 backup.sh
同级目录下新建 index.js
脚本:
const { exec } = require('child_process')
const got = require('got')
// Server sendkey 更换你的 Token
const sendkey = 'PDU7221T3T2Axxxx'
let title = ''
let message = ''
exec('bash /home/ubuntu/backup/backup.sh', (error, stdout, stderr) => {
if (error) {
title = error.toString()
} else {
title = `${parseTime(new Date())} 备份成功!`
message = `${stdout} - ${stderr}`
}
// Server
const url = `https://api2.pushdeer.com/message/push`
got.post(url, {
json: {
text: title,
desp: message,
pushkey: sendkey
}
}).then(response => {
console.log('PushDeer 通知', response)
}).catch(err => {
console.log('PushDeer 错误通知', err)
})
});
/**
* 时间格式化
* @param {*} time
* @param {*} cFormat
* @returns
*/
function parseTime(time, cFormat) {
if (arguments.length === 0) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
上面涉及到的 api
参考文档:
PushDeer:https://www.pushdeer.com/official.html
然后删除之前的任务并且添加下面定时任务:
# 在任务表添加下列任务
0 0 * * * /usr/bin/node /home/ubuntu/backup/index.js # 每天 0 点执行
*/5 * * * * /usr/bin/node /home/ubuntu/backup/index.js # 每5分钟执行一次 可以拿这个测试
代码记录:[Ghost-Theme/BackupTools at master · JaxsonWang/Ghost-Theme · GitHub](