mirror of
https://github.com/wolfydw/backup_OBS.git
synced 2026-05-08 06:37:02 +08:00
Add automated install and stable updates
This commit is contained in:
Executable
+132
@@ -0,0 +1,132 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
SCRIPT_PATH="${BASH_SOURCE[0]:-$0}"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname -- "$SCRIPT_PATH")" && pwd -P)"
|
||||||
|
INSTALL_MODE="system"
|
||||||
|
INSTALL_USER="root"
|
||||||
|
SYSTEMD_DIR="/etc/systemd/system"
|
||||||
|
DRY_RUN=false
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'USAGE'
|
||||||
|
用法:
|
||||||
|
./install.sh [--user=NAME] [--mode=system|user] [--dry-run]
|
||||||
|
|
||||||
|
说明:
|
||||||
|
- system 模式会安装到 /etc/systemd/system
|
||||||
|
- user 模式会安装到 ~/.config/systemd/user
|
||||||
|
- 不会覆盖已有 env.conf 和 exclude.user.list
|
||||||
|
- dry-run 只打印将执行的动作,不实际写入 systemd
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--user=*) INSTALL_USER="${1#*=}"; shift;;
|
||||||
|
--mode=*) INSTALL_MODE="${1#*=}"; shift;;
|
||||||
|
--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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
need_cmd systemctl
|
||||||
|
need_cmd install
|
||||||
|
need_cmd sed
|
||||||
|
|
||||||
|
if [[ "$INSTALL_MODE" != "system" && "$INSTALL_MODE" != "user" ]]; then
|
||||||
|
echo "无效 --mode:$INSTALL_MODE" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$INSTALL_MODE" == "system" && "$(id -u)" -ne 0 ]]; then
|
||||||
|
echo "system 模式需要 root 权限" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$INSTALL_MODE" == "user" ]]; then
|
||||||
|
HOME_DIR="$(getent passwd "$INSTALL_USER" | cut -d: -f6)"
|
||||||
|
if [[ -z "$HOME_DIR" ]]; then
|
||||||
|
echo "无法找到用户:$INSTALL_USER" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
SYSTEMD_DIR="${HOME_DIR}/.config/systemd/user"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${SCRIPT_DIR}/systemd"
|
||||||
|
|
||||||
|
if [[ ! -f "${SCRIPT_DIR}/env.conf" ]]; then
|
||||||
|
if $DRY_RUN; then
|
||||||
|
echo "[dry-run] 将创建 ${SCRIPT_DIR}/env.conf"
|
||||||
|
else
|
||||||
|
cp "${SCRIPT_DIR}/env.conf.example" "${SCRIPT_DIR}/env.conf"
|
||||||
|
echo "已创建 ${SCRIPT_DIR}/env.conf"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "${SCRIPT_DIR}/exclude.user.list" ]]; then
|
||||||
|
if $DRY_RUN; then
|
||||||
|
echo "[dry-run] 将创建 ${SCRIPT_DIR}/exclude.user.list"
|
||||||
|
else
|
||||||
|
cp "${SCRIPT_DIR}/exclude.user.list.example" "${SCRIPT_DIR}/exclude.user.list"
|
||||||
|
echo "已创建 ${SCRIPT_DIR}/exclude.user.list"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod 755 \
|
||||||
|
"${SCRIPT_DIR}/backup.sh" \
|
||||||
|
"${SCRIPT_DIR}/clean_backups.sh" \
|
||||||
|
"${SCRIPT_DIR}/lib/telegram.sh" \
|
||||||
|
"${SCRIPT_DIR}/install.sh" \
|
||||||
|
"${SCRIPT_DIR}/update.sh"
|
||||||
|
|
||||||
|
if $DRY_RUN; then
|
||||||
|
echo "[dry-run] 目标 systemd 目录:$SYSTEMD_DIR"
|
||||||
|
else
|
||||||
|
mkdir -p "$SYSTEMD_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
render_unit() {
|
||||||
|
local src="$1"
|
||||||
|
local dst="$2"
|
||||||
|
if $DRY_RUN; then
|
||||||
|
echo "[dry-run] 将渲染 $(basename "$src") -> $dst"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sed \
|
||||||
|
-e "s|__WORKDIR__|${SCRIPT_DIR}|g" \
|
||||||
|
-e "s|__RUN_USER__|${INSTALL_USER}|g" \
|
||||||
|
"$src" > "$dst"
|
||||||
|
|
||||||
|
if [[ "$INSTALL_MODE" == "user" ]]; then
|
||||||
|
sed -i '/^User=__RUN_USER__$/d;/^User=/d' "$dst"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
render_unit "${SCRIPT_DIR}/systemd/backup-obs-update.service" "${SYSTEMD_DIR}/backup-obs-update.service"
|
||||||
|
render_unit "${SCRIPT_DIR}/systemd/backup-obs-update.timer" "${SYSTEMD_DIR}/backup-obs-update.timer"
|
||||||
|
|
||||||
|
if $DRY_RUN; then
|
||||||
|
echo "[dry-run] 将执行 systemctl daemon-reload"
|
||||||
|
echo "[dry-run] 将启用 backup-obs-update.timer"
|
||||||
|
elif [[ "$INSTALL_MODE" == "system" ]]; then
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now backup-obs-update.timer
|
||||||
|
echo "已启用 system timer:backup-obs-update.timer"
|
||||||
|
echo "查看状态:systemctl status backup-obs-update.timer"
|
||||||
|
echo "查看日志:journalctl -u backup-obs-update.service -n 100"
|
||||||
|
else
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
systemctl --user enable --now backup-obs-update.timer
|
||||||
|
echo "已启用 user timer:backup-obs-update.timer"
|
||||||
|
echo "查看状态:systemctl --user status backup-obs-update.timer"
|
||||||
|
echo "查看日志:journalctl --user -u backup-obs-update.service -n 100"
|
||||||
|
fi
|
||||||
@@ -61,6 +61,111 @@ EOF
|
|||||||
./clean_backups.sh --retain-days=5
|
./clean_backups.sh --retain-days=5
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 首次部署
|
||||||
|
|
||||||
|
新机器首次部署推荐流程:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone <你的仓库地址> /root/backup_OBS
|
||||||
|
cd /root/backup_OBS
|
||||||
|
./install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
`install.sh` 会自动完成:
|
||||||
|
|
||||||
|
- 如果不存在,则创建 `env.conf`
|
||||||
|
- 如果不存在,则创建 `exclude.user.list`
|
||||||
|
- 修正脚本执行权限
|
||||||
|
- 安装 `systemd` 更新任务
|
||||||
|
- 启用 `backup-obs-update.timer`
|
||||||
|
|
||||||
|
默认使用 system 模式,也就是安装到 `/etc/systemd/system`。
|
||||||
|
|
||||||
|
可选参数:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./install.sh --mode=system
|
||||||
|
./install.sh --mode=user --user=root
|
||||||
|
```
|
||||||
|
|
||||||
|
说明:
|
||||||
|
|
||||||
|
- `system` 模式需要 root 权限
|
||||||
|
- `user` 模式会安装到 `~/.config/systemd/user`
|
||||||
|
- 安装脚本不会覆盖已有的 `env.conf` 和 `exclude.user.list`
|
||||||
|
|
||||||
|
常用查看命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl status backup-obs-update.timer
|
||||||
|
journalctl -u backup-obs-update.service -n 100
|
||||||
|
```
|
||||||
|
|
||||||
|
## 自动更新
|
||||||
|
|
||||||
|
仓库内提供了一个统一更新脚本:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./update.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
它会执行:
|
||||||
|
|
||||||
|
- `git fetch --tags origin`
|
||||||
|
- 默认更新 `stable` 分支,或切换到你指定的 tag / 分支
|
||||||
|
- 修正脚本执行权限
|
||||||
|
- 自动执行一次 `./backup.sh --dry-run` 自检
|
||||||
|
|
||||||
|
也可以手动指定版本:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./update.sh
|
||||||
|
./update.sh stable
|
||||||
|
./update.sh main
|
||||||
|
./update.sh v1.2.0
|
||||||
|
```
|
||||||
|
|
||||||
|
配合 `systemd timer` 后,机器会定时自动执行 `update.sh`。
|
||||||
|
|
||||||
|
## GitHub 多机发布流程
|
||||||
|
|
||||||
|
推荐流程:
|
||||||
|
|
||||||
|
1. 在一台测试机或开发环境修改脚本并提交到 GitHub。
|
||||||
|
2. 在测试机手动运行:
|
||||||
|
- `./update.sh main`
|
||||||
|
- `./backup.sh --dry-run`
|
||||||
|
- `./backup.sh`
|
||||||
|
- `./clean_backups.sh --retain-days=100000`
|
||||||
|
3. 确认备份、清理、Telegram 通知都正常。
|
||||||
|
4. 打稳定版本标签,例如:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag v1.2.0
|
||||||
|
git push origin v1.2.0
|
||||||
|
```
|
||||||
|
|
||||||
|
5. 生产机器可以手动执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./update.sh v1.2.0
|
||||||
|
```
|
||||||
|
|
||||||
|
或者让 `systemd` 定时器长期跟随 `stable` 分支。
|
||||||
|
|
||||||
|
更稳的做法是:
|
||||||
|
|
||||||
|
- `main` 用来持续迭代
|
||||||
|
- `stable` 用来给其他机器自动更新
|
||||||
|
- tag 用来留档和回滚
|
||||||
|
|
||||||
|
推荐的发布方式:
|
||||||
|
|
||||||
|
1. 日常修改提交到 `main`
|
||||||
|
2. 测试机验证 `main`
|
||||||
|
3. 验证通过后,把 `main` 合并到 `stable`
|
||||||
|
4. 其他机器的 `systemd timer` 自动执行 `./update.sh stable`
|
||||||
|
|
||||||
## 排除规则
|
## 排除规则
|
||||||
|
|
||||||
脚本会同时读取两个排除文件:
|
脚本会同时读取两个排除文件:
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Update backup_OBS scripts from Git
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
User=__RUN_USER__
|
||||||
|
WorkingDirectory=__WORKDIR__
|
||||||
|
ExecStart=__WORKDIR__/update.sh stable
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Run backup_OBS updater periodically
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnBootSec=10m
|
||||||
|
OnUnitActiveSec=1h
|
||||||
|
Persistent=true
|
||||||
|
Unit=backup-obs-update.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
SCRIPT_PATH="${BASH_SOURCE[0]:-$0}"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname -- "$SCRIPT_PATH")" && pwd -P)"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'USAGE'
|
||||||
|
用法:
|
||||||
|
./update.sh [branch-or-tag]
|
||||||
|
|
||||||
|
说明:
|
||||||
|
- 不带参数时,默认更新 stable 分支
|
||||||
|
- 带参数时,可以切换到指定分支或 tag
|
||||||
|
- 更新后会自动执行一次 ./backup.sh --dry-run 自检
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
need_cmd() {
|
||||||
|
command -v "$1" >/dev/null 2>&1 || {
|
||||||
|
echo "缺少命令:$1" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
need_cmd git
|
||||||
|
need_cmd bash
|
||||||
|
|
||||||
|
TARGET_REF="${1:-}"
|
||||||
|
if [[ -z "$TARGET_REF" ]]; then
|
||||||
|
TARGET_REF="stable"
|
||||||
|
fi
|
||||||
|
|
||||||
|
git fetch --tags origin
|
||||||
|
|
||||||
|
if git show-ref --verify --quiet "refs/tags/${TARGET_REF}"; then
|
||||||
|
git checkout "${TARGET_REF}"
|
||||||
|
else
|
||||||
|
git checkout "${TARGET_REF}"
|
||||||
|
git pull --ff-only origin "${TARGET_REF}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod 755 \
|
||||||
|
"${SCRIPT_DIR}/backup.sh" \
|
||||||
|
"${SCRIPT_DIR}/clean_backups.sh" \
|
||||||
|
"${SCRIPT_DIR}/lib/telegram.sh" \
|
||||||
|
"${SCRIPT_DIR}/install.sh" \
|
||||||
|
"${SCRIPT_DIR}/update.sh"
|
||||||
|
|
||||||
|
bash "${SCRIPT_DIR}/backup.sh" --dry-run
|
||||||
Reference in New Issue
Block a user