用GitHub Actions实现memos备份

正文

我的memos是在replit提供的免费服务器上部署的,数据也保存在这个服务器上,我怕哪天上面的数据没了,所以写了个GitHub Actions备份脚本

可以新建一个GitHub仓库,并开启Actions的读写权限:仓库的Settings-Actions-General-Workflow permissions-选择Read and write permissions

.github\workflows\main.yml中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
name: Backup Memos

on:
schedule:
- cron: "0 */4 * * *" # 每隔4小时执行一次
workflow_dispatch:
jobs:
backup:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8

- name: 设置时区
run: sudo timedatectl set-timezone 'Asia/Shanghai'

- name: Run backup script
run: |
pip install requests
python backup_script.py

- name: Commit and push changes
run: |
git config --global user.email "【email】"
git config --global user.name "【name】"
git add .
git commit -m "Auto backup memos"
git push

backup_script.py中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import requests
import json
from datetime import datetime

# Memos API URL
api_url = "https://66b4d66d-5794-4c83-9907-5519995b7d8e-00-15cwgy9gwbwnv.pike.replit.dev/api/v1/memo?creatorId=1"

try:
# 发送 GET 请求到 API
response = requests.get(api_url)

print("Response status code:", response.status_code)
print("Response content:", response.text)

# 检查请求是否成功
if response.status_code == 200:
# 将 JSON 响应解析为 Python 对象
memos_data = response.json()

# 将当前时间作为文件名
current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
filename = f"backup/memos/memos_backup_{current_time}.json"

# 将数据保存到文件
with open(filename, "w", encoding="utf-8") as file:
json.dump(memos_data, file, ensure_ascii=False, indent=2)

print(f"Backup successful. Data saved to {filename}")
else:
print(f"Error: Unable to fetch data from API. Status code: {response.status_code}")
except requests.exceptions.RequestException as e:
print(f"Error: Unable to fetch data from API. Exception: {e}")
except json.JSONDecodeError as e:
print(f"Error: Unable to decode JSON response. Exception: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")

至此,就完成了备份脚本

番外

关于备份失败

原本把cron设置为"0 0 * * *",让GitHub Actions每天0点定时触发,但结果每次脚本运行request请求都没成功

但是用workflow_dispatch手动触发却可以成功

定时触发的时间是每天的UTC时间0点,难道运行memos的服务器也在这个时间重启了?

打开replit服务器,使用uptime命令,显示:

1
09:00:16  up   1:20,  0 users,  load average: 4.18, 7.26, 7.25

服务器运行了1小时20分钟,说明短时间重启过,说明是有可能的(免费服务器咱也不能要求太多呀)

先把cron设置为0 */4 * * *,每4小时运行一次脚本,再试试看

后续就是成功了,用每隔4小时执行就成功了,难绷

GitHub Actions时间不准确?

之前没有设置时区的时候,默认使用UTC时间

把cron设置为"0 9 * * *",在UTC时间9点运行(中国17点)

在脚本中使用date命令,运行结果显示Mon Jan 1 09:18:14 UTC 2024

差了18分钟,这里可能是GitHub Actions用于cron调度的时间不准确?

备份得到的json文件转换乘yml文件

后续就是,我不用memos了,而是用静态部署的方式

静态部署是通过类似于友链的方式进行数据展示的,所以我们需要转换成yml文件,脚本可以参考下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import yaml
import json
from datetime import datetime

# 从文件中读取 JSON 数据
with open("backup\memos\memos_backup_2024-01-05_20-10-47.json", "r", encoding="utf-8") as json_file:
json_data = json.load(json_file)

# 转换为目标格式的函数
def convert_to_yaml(data):
res = []
essay_list = []
for item in data:
essay_list.append(
{
"content": item["content"],
"date": datetime.utcfromtimestamp(item["createdTs"]).strftime("%Y/%m/%d %H:%M:%S"),
"from": item["creatorUsername"],
}
)
yaml_data = {
"class_name": "即刻短文",
"essay_number": -1,
"essay_list": essay_list
}
res.append(yaml_data)
return res

# 调用转换函数
yaml_data = convert_to_yaml(json_data)

# 将YAML数据写入文件
with open("output.yml", "w", encoding="utf-8") as file:
yaml.dump(yaml_data, file, default_flow_style=False, allow_unicode=True)

print("Conversion completed. Output written to 'output.yml'")