以下是一个完整的Python脚本,用于定期检查GitHub仓库更新并自动备份旧版本:
import os
import shutil
import subprocess
import time
from datetime import datetime
import re
# 配置参数
REPO_URL = "https://github.com/NanmiCoder/MediaCrawler.git"
REPO_NAME = "MediaCrawler"
BAC_DIR = "bac"
COMMIT_FILE = os.path.join(BAC_DIR, "last_commit.txt")
CHECK_INTERVAL = 3 * 24 * 60 * 60 # 3天的秒数
def get_remote_commit():
"""获取远程仓库的最新commit ID"""
try:
output = subprocess.check_output(
["git", "ls-remote", REPO_URL, "HEAD"],
stderr=subprocess.STDOUT,
text=True
)
return output.split()[0]
except subprocess.CalledProcessError as e:
print(f"获取远程commit失败: {e.output}")
return None
def get_local_commit():
"""从本地文件读取保存的commit ID"""
if os.path.exists(COMMIT_FILE):
with open(COMMIT_FILE, "r") as f:
return f.read().strip()
return None
def save_commit(commit_id):
"""保存commit ID到文件"""
os.makedirs(BAC_DIR, exist_ok=True)
with open(COMMIT_FILE, "w") as f:
f.write(commit_id)
def clone_repo():
"""克隆仓库到当前目录"""
try:
subprocess.run(
["git", "clone", REPO_URL],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
print("仓库克隆成功")
return True
except subprocess.CalledProcessError as e:
print(f"克隆失败: {e.stderr.decode()}")
return False
def backup_existing():
"""备份现有仓库到bac目录"""
if not os.path.exists(REPO_NAME):
return False
# 清理无效字符的时间戳
timestamp = re.sub(r"[^\w-]", "", datetime.now().isoformat(timespec="seconds"))
backup_name = f"{REPO_NAME}_{timestamp}.zip"
backup_path = os.path.join(BAC_DIR, backup_name)
os.makedirs(BAC_DIR, exist_ok=True)
shutil.make_archive(
os.path.join(BAC_DIR, REPO_NAME + "_" + timestamp),
'zip',
os.getcwd(),
REPO_NAME
)
print(f"已备份到: {backup_path}")
# 删除旧仓库
shutil.rmtree(REPO_NAME)
return True
def main():
# 首次运行直接克隆
if not os.path.exists(REPO_NAME):
print("首次运行,克隆仓库...")
if clone_repo():
commit_id = get_remote_commit()
if commit_id:
save_commit(commit_id)
return
while True:
print("\n检查更新...")
remote_commit = get_remote_commit()
local_commit = get_local_commit()
if not remote_commit:
print("无法获取远程commit,等待下次检查")
time.sleep(CHECK_INTERVAL)
continue
print(f"本地commit: {local_commit or '无记录'}")
print(f"远程commit: {remote_commit}")
if remote_commit == local_commit:
print("无新更新")
else:
print("检测到更新,开始备份并克隆新版本")
if backup_existing():
if clone_repo():
save_commit(remote_commit)
print(f"下次检查在 {CHECK_INTERVAL//3600} 小时后...")
time.sleep(CHECK_INTERVAL)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n程序已退出")
功能说明:
-
首次运行:
- 自动克隆指定仓库到当前目录
- 记录当前commit ID到
bac/last_commit.txt
-
定期检查:
- 每3天检查一次远程仓库更新
- 比较本地保存的commit ID和远程最新commit ID
-
更新处理:
- 检测到更新时自动备份现有仓库
- 备份文件命名格式:
MediaCrawler_YYYY-MM-DDTHHMMSS.zip
- 删除旧仓库并克隆最新版本
- 更新commit记录文件
-
备份管理:
- 所有备份保存在
bac/
目录 - 保留完整的仓库历史记录
- 所有备份保存在
使用步骤:
- 将脚本保存为
repo_updater.py
- 安装依赖:
pip install shutil subprocess
- 运行脚本:
python repo_updater.py
注意事项:
- 确保系统已安装Git并配置了环境变量
- 需要Python 3.6+环境
- 脚本会持续运行(后台服务模式),按Ctrl+C退出
- 备份文件会保存在脚本同目录下的
bac/
文件夹 - 首次运行会自动创建仓库目录和备份目录
自定义配置:
- 修改
REPO_URL
更换目标仓库 - 调整
CHECK_INTERVAL
改变检查频率(秒为单位) - 修改
BAC_DIR
改变备份目录名称 - 修改
REPO_NAME
改变本地仓库目录名称
提示:如需部署为后台服务,可使用
nohup python repo_updater.py &
命令在Linux系统后台运行
评论区