编写脚本
This commit is contained in:
11
README.md
11
README.md
@@ -2,13 +2,22 @@
|
|||||||
|
|
||||||
## 功能
|
## 功能
|
||||||
每天从https://git.ociflab.icu/Laplace/backup-list拉取whitelist.md
|
每天从https://git.ociflab.icu/Laplace/backup-list拉取whitelist.md
|
||||||
|
如果没拉取到,则使用前一天拉取并保存的whitelist文件。
|
||||||
|
如果超过三分之一的仓库都拉取错误,则给脚本中设置的server酱3 Pushkey推送警告信息。
|
||||||
然后根据whitelist.md拉取对应的仓库到backup文件夹进行备份
|
然后根据whitelist.md拉取对应的仓库到backup文件夹进行备份
|
||||||
压缩成zip,每天定时备份一次,保留7天。
|
压缩成zip,每天定时备份一次,保留7天。
|
||||||
使用Python。
|
使用bash。
|
||||||
|
|
||||||
## whitelist.md文件结构:
|
## whitelist.md文件结构:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
https://git.ociflab.icu/userA/projectA
|
https://git.ociflab.icu/userA/projectA
|
||||||
https://git.ociflab.icu/userB/projectB
|
https://git.ociflab.icu/userB/projectB
|
||||||
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
## server酱3参考
|
||||||
|
~~~bash
|
||||||
|
# 一行代码即可调用,中文参数需要UrlEncode,长内容建议使用POST
|
||||||
|
curl "https://<uid>.push.ft07.com/send/<sendkey>.send?title=<title>&desp=<desp>"
|
||||||
~~~
|
~~~
|
||||||
192
ociflab-backup.sh
Normal file
192
ociflab-backup.sh
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# OCIFLAB 仓库备份脚本
|
||||||
|
# 每天从 whitelist.md 拉取仓库列表,克隆/更新仓库,压缩备份
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# ---------- 配置区 ----------
|
||||||
|
WHITELIST_URL=""
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
BACKUP_DIR="${SCRIPT_DIR}/backup"
|
||||||
|
WORK_DIR="${SCRIPT_DIR}/work"
|
||||||
|
ARCHIVE_DIR="${SCRIPT_DIR}/archives"
|
||||||
|
WHITELIST_CACHE="${SCRIPT_DIR}/whitelist_cache.md"
|
||||||
|
RETENTION_DAYS=7
|
||||||
|
DATE_STAMP="$(date +%Y%m%d)"
|
||||||
|
|
||||||
|
# server酱3 配置
|
||||||
|
SERVERCHAN_UID="" # 填写你的 UID
|
||||||
|
SERVERCHAN_SENDKEY="" # 填写你的 SendKey
|
||||||
|
|
||||||
|
# ---------- 函数区 ----------
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
|
||||||
|
}
|
||||||
|
|
||||||
|
send_warning() {
|
||||||
|
local title="$1"
|
||||||
|
local desp="$2"
|
||||||
|
if [[ -z "${SERVERCHAN_UID}" ]] || [[ -z "${SERVERCHAN_SENDKEY}" ]]; then
|
||||||
|
log "server酱未配置,跳过推送: ${title}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local resp
|
||||||
|
resp=$(curl -s -o /dev/null -w "%{http_code}" --data-urlencode "title=${title}" --data-urlencode "desp=${desp}" "https://${SERVERCHAN_UID}.push.ft07.com/send/${SERVERCHAN_SENDKEY}.send")
|
||||||
|
if [[ "${resp}" == "200" ]]; then
|
||||||
|
log "警告推送成功: ${title}"
|
||||||
|
else
|
||||||
|
log "警告推送失败(HTTP ${resp}): ${title}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch_whitelist() {
|
||||||
|
log "正在拉取 whitelist.md ..."
|
||||||
|
local http_code
|
||||||
|
http_code=$(curl -s -o "${WHITELIST_CACHE}" -w "%{http_code}" --connect-timeout 10 --max-time 30 "${WHITELIST_URL}")
|
||||||
|
|
||||||
|
if [[ "${http_code}" == "200" ]] && [[ -s "${WHITELIST_CACHE}" ]]; then
|
||||||
|
log "whitelist.md 拉取成功 (HTTP ${http_code})"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "whitelist.md 拉取失败 (HTTP ${http_code}),尝试使用前一天缓存..."
|
||||||
|
if [[ -f "${SCRIPT_DIR}/whitelist_cache.md.yesterday" ]]; then
|
||||||
|
cp "${SCRIPT_DIR}/whitelist_cache.md.yesterday" "${WHITELIST_CACHE}"
|
||||||
|
log "已使用前一天缓存"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "前一天缓存也不存在,无法继续"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_whitelist() {
|
||||||
|
grep -Eo 'https://git\.ociflab\.icu/[^[:space:]]+' "${WHITELIST_CACHE}" | sed 's/[[:space:]]*$//'
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_or_pull_repo() {
|
||||||
|
local repo_url="$1"
|
||||||
|
local repo_name
|
||||||
|
repo_name=$(echo "${repo_url}" | sed 's|https://git\.ociflab\.icu/||' | tr '/' '_')
|
||||||
|
local repo_path="${WORK_DIR}/${repo_name}"
|
||||||
|
|
||||||
|
if [[ -d "${repo_path}/.git" ]]; then
|
||||||
|
log " 更新: ${repo_url}"
|
||||||
|
if ! git -C "${repo_path}" pull --ff-only 2>&1; then
|
||||||
|
log " 更新失败: ${repo_url},尝试重新克隆..."
|
||||||
|
rm -rf "${repo_path}"
|
||||||
|
if ! git clone --depth 1 "${repo_url}" "${repo_path}" 2>&1; then
|
||||||
|
log " 重新克隆也失败: ${repo_url}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log " 克隆: ${repo_url}"
|
||||||
|
rm -rf "${repo_path}"
|
||||||
|
if ! git clone --depth 1 "${repo_url}" "${repo_path}" 2>&1; then
|
||||||
|
log " 克隆失败: ${repo_url}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
backup_repos() {
|
||||||
|
local whitelist=("$@")
|
||||||
|
local total=${#whitelist[@]}
|
||||||
|
local failed=0
|
||||||
|
local failed_list=""
|
||||||
|
|
||||||
|
log "共 ${total} 个仓库待备份"
|
||||||
|
|
||||||
|
for repo_url in "${whitelist[@]}"; do
|
||||||
|
[[ -z "${repo_url}" ]] && continue
|
||||||
|
if ! clone_or_pull_repo "${repo_url}"; then
|
||||||
|
failed=$((failed + 1))
|
||||||
|
failed_list="${failed_list}${repo_url}\n"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 检查错误率:超过三分之一则发送警告
|
||||||
|
if [[ ${total} -gt 0 ]]; then
|
||||||
|
local threshold=$((total / 3))
|
||||||
|
if [[ ${failed} -gt ${threshold} ]]; then
|
||||||
|
local warn_desp="备份失败 ${failed}/${total} 个仓库,超过三分之一。\n失败列表:\n${failed_list}"
|
||||||
|
send_warning "OCIFLAB备份异常 - ${failed}/${total} 仓库失败" "${warn_desp}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "备份完成: 成功 $((total - failed)) 个, 失败 ${failed} 个"
|
||||||
|
}
|
||||||
|
|
||||||
|
create_archive() {
|
||||||
|
log "正在压缩备份..."
|
||||||
|
mkdir -p "${ARCHIVE_DIR}"
|
||||||
|
|
||||||
|
local archive_name="ociflab-backup-${DATE_STAMP}.zip"
|
||||||
|
local archive_path="${ARCHIVE_DIR}/${archive_name}"
|
||||||
|
|
||||||
|
if [[ -d "${WORK_DIR}" ]] && [[ -n "$(ls -A "${WORK_DIR}" 2>/dev/null)" ]]; then
|
||||||
|
cd "${WORK_DIR}"
|
||||||
|
zip -r "${archive_path}" . -q
|
||||||
|
cd "${SCRIPT_DIR}"
|
||||||
|
log "压缩完成: ${archive_path}"
|
||||||
|
else
|
||||||
|
log "工作目录为空,跳过压缩"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_old_archives() {
|
||||||
|
log "清理 ${RETENTION_DAYS} 天前的备份..."
|
||||||
|
find "${ARCHIVE_DIR}" -name "ociflab-backup-*.zip" -type f -mtime +${RETENTION_DAYS} -delete 2>/dev/null || true
|
||||||
|
log "清理完成"
|
||||||
|
}
|
||||||
|
|
||||||
|
persist_yesterday_whitelist() {
|
||||||
|
if [[ -f "${WHITELIST_CACHE}" ]]; then
|
||||||
|
cp "${WHITELIST_CACHE}" "${SCRIPT_DIR}/whitelist_cache.md.yesterday"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------- 主流程 ----------
|
||||||
|
|
||||||
|
main() {
|
||||||
|
log "========== OCIFLAB 备份开始 =========="
|
||||||
|
|
||||||
|
mkdir -p "${WORK_DIR}" "${ARCHIVE_DIR}"
|
||||||
|
|
||||||
|
# 1. 拉取白名单
|
||||||
|
if ! fetch_whitelist; then
|
||||||
|
log "无法获取白名单,退出"
|
||||||
|
send_warning "OCIFLAB备份失败" "无法拉取 whitelist.md 且无前一天缓存"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. 解析仓库列表
|
||||||
|
mapfile -t repos < <(parse_whitelist)
|
||||||
|
|
||||||
|
if [[ ${#repos[@]} -eq 0 ]]; then
|
||||||
|
log "白名单为空,退出"
|
||||||
|
send_warning "OCIFLAB备份失败" "whitelist.md 中无有效仓库地址"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. 克隆/更新仓库
|
||||||
|
backup_repos "${repos[@]}"
|
||||||
|
|
||||||
|
# 4. 压缩归档
|
||||||
|
create_archive
|
||||||
|
|
||||||
|
# 5. 清理旧备份
|
||||||
|
cleanup_old_archives
|
||||||
|
|
||||||
|
# 6. 保存今天的白名单供明天备用
|
||||||
|
persist_yesterday_whitelist
|
||||||
|
|
||||||
|
log "========== OCIFLAB 备份完成 =========="
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Reference in New Issue
Block a user