mirror of
https://github.com/wolfydw/backup_OBS.git
synced 2026-05-08 06:37:02 +08:00
Add reusable obsutil installer and update flow
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
# - 打包多目录(支持 pigz),生成 SHA256 校验,obsutil 分片/并发上传
|
# - 打包多目录(支持 pigz),生成 SHA256 校验,obsutil 分片/并发上传
|
||||||
# - 上传 .tar.gz 以及 .tar.gz.sha256,并下载远端 .sha256 比对确保完整性
|
# - 上传 .tar.gz 以及 .tar.gz.sha256,并下载远端 .sha256 比对确保完整性
|
||||||
# - 成功/失败写入日志并 Telegram 通知
|
# - 成功/失败写入日志并 Telegram 通知
|
||||||
# - 支持 --dry-run / --verify / --keep-local / --concurrency / --rate / --label / --sse
|
# - 支持 --dry-run / --self-check / --verify / --keep-local / --concurrency / --rate / --label / --sse
|
||||||
# 退出码:0 成功;2 配置缺失;3 打包失败;4 上传失败;5 校验失败
|
# 退出码:0 成功;2 配置缺失;3 打包失败;4 上传失败;5 校验失败
|
||||||
|
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
@@ -81,6 +81,7 @@ BACKUP_PATHS=()
|
|||||||
|
|
||||||
KEEP_LOCAL=false
|
KEEP_LOCAL=false
|
||||||
DRY_RUN=false
|
DRY_RUN=false
|
||||||
|
SELF_CHECK=false
|
||||||
VERIFY_ONLY=false
|
VERIFY_ONLY=false
|
||||||
CLI_LABEL=""
|
CLI_LABEL=""
|
||||||
CLI_SSE="none"
|
CLI_SSE="none"
|
||||||
@@ -92,7 +93,7 @@ GPG_SYM=false
|
|||||||
usage() {
|
usage() {
|
||||||
cat <<'USAGE'
|
cat <<'USAGE'
|
||||||
用法:
|
用法:
|
||||||
./backup.sh [--dry-run] [--verify] [--keep-local]
|
./backup.sh [--dry-run] [--self-check] [--verify] [--keep-local]
|
||||||
[--concurrency=N] [--rate=10MB/s]
|
[--concurrency=N] [--rate=10MB/s]
|
||||||
[--label=NAME]
|
[--label=NAME]
|
||||||
[--sse=none|kms|aes256]
|
[--sse=none|kms|aes256]
|
||||||
@@ -103,6 +104,7 @@ USAGE
|
|||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--dry-run) DRY_RUN=true; shift;;
|
--dry-run) DRY_RUN=true; shift;;
|
||||||
|
--self-check) DRY_RUN=true; SELF_CHECK=true; shift;;
|
||||||
--verify) VERIFY_ONLY=true; shift;;
|
--verify) VERIFY_ONLY=true; shift;;
|
||||||
--keep-local) KEEP_LOCAL=true; shift;;
|
--keep-local) KEEP_LOCAL=true; shift;;
|
||||||
--concurrency=*) CLI_CONCURRENCY="${1#*=}"; shift;;
|
--concurrency=*) CLI_CONCURRENCY="${1#*=}"; shift;;
|
||||||
@@ -524,6 +526,10 @@ if $DRY_RUN; then
|
|||||||
log "INFO" "Dry-run 模式:不执行上传。归档:${ARCHIVE_BASE} 大小:${BACKUP_SIZE_HUMAN}"
|
log "INFO" "Dry-run 模式:不执行上传。归档:${ARCHIVE_BASE} 大小:${BACKUP_SIZE_HUMAN}"
|
||||||
log "INFO" "本次总用时:${SECONDS}s"
|
log "INFO" "本次总用时:${SECONDS}s"
|
||||||
tg_backup_dryrun "$LABEL" "$(date +'%Y-%m-%d %H:%M:%S')" "$(printf '%s\n' "${BACKUP_PATHS[@]}")" "$(tg_read_user_excludes "$USER_EXCLUDE_FILE")" "$ARCHIVE_BASE" "$BACKUP_SIZE_HUMAN" "${PACK_SECONDS}s"
|
tg_backup_dryrun "$LABEL" "$(date +'%Y-%m-%d %H:%M:%S')" "$(printf '%s\n' "${BACKUP_PATHS[@]}")" "$(tg_read_user_excludes "$USER_EXCLUDE_FILE")" "$ARCHIVE_BASE" "$BACKUP_SIZE_HUMAN" "${PACK_SECONDS}s"
|
||||||
|
if $SELF_CHECK; then
|
||||||
|
rm -f "$ARCHIVE_PATH" "$SHA_PATH" || true
|
||||||
|
log "INFO" "Self-check 模式:已删除本地自检归档与校验文件"
|
||||||
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
+18
@@ -14,6 +14,7 @@ usage() {
|
|||||||
./install.sh [--user=NAME] [--mode=system|user] [--dry-run]
|
./install.sh [--user=NAME] [--mode=system|user] [--dry-run]
|
||||||
|
|
||||||
说明:
|
说明:
|
||||||
|
- 若未检测到仓库内 obsutil,会自动调用 lib/obsutil.sh 安装
|
||||||
- system 模式会安装到 /etc/systemd/system
|
- system 模式会安装到 /etc/systemd/system
|
||||||
- user 模式会安装到 ~/.config/systemd/user
|
- user 模式会安装到 ~/.config/systemd/user
|
||||||
- 不会覆盖已有 env.conf 和 exclude.user.list
|
- 不会覆盖已有 env.conf 和 exclude.user.list
|
||||||
@@ -61,6 +62,18 @@ if [[ "$INSTALL_MODE" == "user" ]]; then
|
|||||||
SYSTEMD_DIR="${HOME_DIR}/.config/systemd/user"
|
SYSTEMD_DIR="${HOME_DIR}/.config/systemd/user"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -f "${SCRIPT_DIR}/obsutil" ]]; then
|
||||||
|
chmod 755 "${SCRIPT_DIR}/obsutil"
|
||||||
|
echo "已检测到仓库内 obsutil:${SCRIPT_DIR}/obsutil"
|
||||||
|
else
|
||||||
|
chmod 755 "${SCRIPT_DIR}/lib/obsutil.sh"
|
||||||
|
if $DRY_RUN; then
|
||||||
|
bash "${SCRIPT_DIR}/lib/obsutil.sh" --dry-run
|
||||||
|
else
|
||||||
|
bash "${SCRIPT_DIR}/lib/obsutil.sh"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
mkdir -p "${SCRIPT_DIR}/systemd"
|
mkdir -p "${SCRIPT_DIR}/systemd"
|
||||||
|
|
||||||
if [[ ! -f "${SCRIPT_DIR}/env.conf" ]]; then
|
if [[ ! -f "${SCRIPT_DIR}/env.conf" ]]; then
|
||||||
@@ -84,10 +97,15 @@ fi
|
|||||||
chmod 755 \
|
chmod 755 \
|
||||||
"${SCRIPT_DIR}/backup.sh" \
|
"${SCRIPT_DIR}/backup.sh" \
|
||||||
"${SCRIPT_DIR}/clean_backups.sh" \
|
"${SCRIPT_DIR}/clean_backups.sh" \
|
||||||
|
"${SCRIPT_DIR}/lib/obsutil.sh" \
|
||||||
"${SCRIPT_DIR}/lib/telegram.sh" \
|
"${SCRIPT_DIR}/lib/telegram.sh" \
|
||||||
"${SCRIPT_DIR}/install.sh" \
|
"${SCRIPT_DIR}/install.sh" \
|
||||||
"${SCRIPT_DIR}/update.sh"
|
"${SCRIPT_DIR}/update.sh"
|
||||||
|
|
||||||
|
if [[ -f "${SCRIPT_DIR}/obsutil" ]]; then
|
||||||
|
chmod 755 "${SCRIPT_DIR}/obsutil"
|
||||||
|
fi
|
||||||
|
|
||||||
if $DRY_RUN; then
|
if $DRY_RUN; then
|
||||||
echo "[dry-run] 目标 systemd 目录:$SYSTEMD_DIR"
|
echo "[dry-run] 目标 systemd 目录:$SYSTEMD_DIR"
|
||||||
else
|
else
|
||||||
|
|||||||
Executable
+115
@@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# 下载或更新仓库内的 obsutil 二进制。
|
||||||
|
# - 默认安装到仓库根目录下的 ./obsutil
|
||||||
|
# - 若系统已有 obsutil,不会覆盖;只管理仓库内副本
|
||||||
|
# - install.sh 和手动维护都可复用这个脚本
|
||||||
|
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
SCRIPT_PATH="${BASH_SOURCE[0]:-$0}"
|
||||||
|
LIB_DIR="$(cd "$(dirname -- "$SCRIPT_PATH")" && pwd -P)"
|
||||||
|
ROOT_DIR="$(cd "${LIB_DIR}/.." && pwd -P)"
|
||||||
|
TARGET_BIN="${ROOT_DIR}/obsutil"
|
||||||
|
DRY_RUN=false
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'USAGE'
|
||||||
|
用法:
|
||||||
|
./lib/obsutil.sh [--dry-run]
|
||||||
|
|
||||||
|
说明:
|
||||||
|
- 下载并安装或更新仓库内的 ./obsutil
|
||||||
|
- 默认覆盖仓库里的旧版本
|
||||||
|
- dry-run 只打印将执行的动作,不实际下载
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--dry-run) DRY_RUN=true; shift ;;
|
||||||
|
-h|--help) usage; exit 0 ;;
|
||||||
|
*) echo "未知参数:$1" >&2; usage; exit 2 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
need_cmd() {
|
||||||
|
command -v "$1" >/dev/null 2>&1 || {
|
||||||
|
echo "缺少命令:$1" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
download_file() {
|
||||||
|
local url="$1"
|
||||||
|
local output="$2"
|
||||||
|
|
||||||
|
if command -v curl >/dev/null 2>&1; then
|
||||||
|
curl -fsSL "$url" -o "$output"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v wget >/dev/null 2>&1; then
|
||||||
|
wget -qO "$output" "$url"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "缺少下载工具:curl 或 wget" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_package_name() {
|
||||||
|
case "$(uname -m)" in
|
||||||
|
x86_64|amd64) printf '%s\n' "obsutil_linux_amd64.tar.gz" ;;
|
||||||
|
aarch64|arm64) printf '%s\n' "obsutil_linux_arm64.tar.gz" ;;
|
||||||
|
*)
|
||||||
|
echo "不支持的 CPU 架构:$(uname -m)" >&2
|
||||||
|
echo "请手动安装 obsutil 后再试" >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
need_cmd install
|
||||||
|
need_cmd tar
|
||||||
|
|
||||||
|
PACKAGE_NAME="$(resolve_package_name)"
|
||||||
|
DOWNLOAD_URL="https://obs-community-intl.obs.ap-southeast-1.myhuaweicloud.com/obsutil/current/${PACKAGE_NAME}"
|
||||||
|
|
||||||
|
if $DRY_RUN; then
|
||||||
|
if [[ -x "$TARGET_BIN" ]]; then
|
||||||
|
echo "[dry-run] 将更新仓库内 obsutil:${TARGET_BIN}"
|
||||||
|
else
|
||||||
|
echo "[dry-run] 将安装仓库内 obsutil:${TARGET_BIN}"
|
||||||
|
fi
|
||||||
|
echo "[dry-run] 下载地址:${DOWNLOAD_URL}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
TMP_DIR="$(mktemp -d)"
|
||||||
|
ARCHIVE_PATH="${TMP_DIR}/${PACKAGE_NAME}"
|
||||||
|
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||||
|
|
||||||
|
if [[ -x "$TARGET_BIN" ]]; then
|
||||||
|
echo "开始更新仓库内 obsutil:${TARGET_BIN}"
|
||||||
|
else
|
||||||
|
echo "开始安装仓库内 obsutil:${TARGET_BIN}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
download_file "$DOWNLOAD_URL" "$ARCHIVE_PATH"
|
||||||
|
tar -xzf "$ARCHIVE_PATH" -C "$TMP_DIR"
|
||||||
|
|
||||||
|
BINARY_PATH="$(find "$TMP_DIR" -type f -name obsutil | head -n 1)"
|
||||||
|
if [[ -z "$BINARY_PATH" ]]; then
|
||||||
|
echo "下载包中未找到 obsutil 可执行文件" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
install -m 755 "$BINARY_PATH" "$TARGET_BIN"
|
||||||
|
VERSION_OUTPUT="$("$TARGET_BIN" version 2>/dev/null || true)"
|
||||||
|
if [[ -z "$VERSION_OUTPUT" ]]; then
|
||||||
|
echo "obsutil 已安装,但运行校验失败:${TARGET_BIN}" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "obsutil 已就绪:${TARGET_BIN}"
|
||||||
|
echo "$VERSION_OUTPUT" | head -n 1
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
- `backup.sh`:打包目录、生成 `sha256`、上传到 OBS、下载远端校验文件做一致性校验
|
- `backup.sh`:打包目录、生成 `sha256`、上传到 OBS、下载远端校验文件做一致性校验
|
||||||
- `clean_backups.sh`:按文件名日期清理旧备份
|
- `clean_backups.sh`:按文件名日期清理旧备份
|
||||||
|
- `lib/obsutil.sh`:下载或更新仓库根目录下的 `./obsutil`
|
||||||
- `lib/telegram.sh`:统一处理 Telegram 通知模板和发送逻辑
|
- `lib/telegram.sh`:统一处理 Telegram 通知模板和发送逻辑
|
||||||
|
|
||||||
## 配置
|
## 配置
|
||||||
@@ -49,6 +50,12 @@ EOF
|
|||||||
./backup.sh --dry-run
|
./backup.sh --dry-run
|
||||||
```
|
```
|
||||||
|
|
||||||
|
仅做自检,且不保留本地归档:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./backup.sh --self-check
|
||||||
|
```
|
||||||
|
|
||||||
检查远端前缀是否可访问:
|
检查远端前缀是否可访问:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -73,6 +80,7 @@ cd /root/backup_OBS
|
|||||||
|
|
||||||
`install.sh` 会自动完成:
|
`install.sh` 会自动完成:
|
||||||
|
|
||||||
|
- 如果未检测到仓库根目录下的 `./obsutil`,则自动调用 `./lib/obsutil.sh`
|
||||||
- 如果不存在,则创建 `env.conf`
|
- 如果不存在,则创建 `env.conf`
|
||||||
- 如果不存在,则创建 `exclude.user.list`
|
- 如果不存在,则创建 `exclude.user.list`
|
||||||
- 修正脚本执行权限
|
- 修正脚本执行权限
|
||||||
@@ -93,6 +101,14 @@ cd /root/backup_OBS
|
|||||||
- `system` 模式需要 root 权限
|
- `system` 模式需要 root 权限
|
||||||
- `user` 模式会安装到 `~/.config/systemd/user`
|
- `user` 模式会安装到 `~/.config/systemd/user`
|
||||||
- 安装脚本不会覆盖已有的 `env.conf` 和 `exclude.user.list`
|
- 安装脚本不会覆盖已有的 `env.conf` 和 `exclude.user.list`
|
||||||
|
- `install.sh` 和后续脚本都只使用仓库根目录下的 `./obsutil`
|
||||||
|
- `obsutil` 安装完成后,首次仍需手动执行 `./obsutil config -interactive`
|
||||||
|
|
||||||
|
如果你想手动安装或更新仓库根目录下的 `./obsutil`,可以直接执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./lib/obsutil.sh
|
||||||
|
```
|
||||||
|
|
||||||
常用查看命令:
|
常用查看命令:
|
||||||
|
|
||||||
@@ -114,7 +130,7 @@ journalctl -u backup-obs-update.service -n 100
|
|||||||
- `git fetch --tags origin`
|
- `git fetch --tags origin`
|
||||||
- 默认更新 `stable` 分支,或切换到你指定的 tag / 分支
|
- 默认更新 `stable` 分支,或切换到你指定的 tag / 分支
|
||||||
- 修正脚本执行权限
|
- 修正脚本执行权限
|
||||||
- 自动执行一次 `./backup.sh --dry-run` 自检
|
- 自动执行一次 `./backup.sh --self-check` 自检
|
||||||
|
|
||||||
也可以手动指定版本:
|
也可以手动指定版本:
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ usage() {
|
|||||||
说明:
|
说明:
|
||||||
- 不带参数时,默认更新 stable 分支
|
- 不带参数时,默认更新 stable 分支
|
||||||
- 带参数时,可以切换到指定分支或 tag
|
- 带参数时,可以切换到指定分支或 tag
|
||||||
- 更新后会自动执行一次 ./backup.sh --dry-run 自检
|
- 更新后会自动执行一次 ./backup.sh --self-check 自检
|
||||||
USAGE
|
USAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,4 +53,4 @@ chmod 755 \
|
|||||||
"${SCRIPT_DIR}/install.sh" \
|
"${SCRIPT_DIR}/install.sh" \
|
||||||
"${SCRIPT_DIR}/update.sh"
|
"${SCRIPT_DIR}/update.sh"
|
||||||
|
|
||||||
bash "${SCRIPT_DIR}/backup.sh" --dry-run
|
bash "${SCRIPT_DIR}/backup.sh" --self-check
|
||||||
|
|||||||
Reference in New Issue
Block a user