Files
backup_OBS/install.sh
T
2026-03-16 20:23:19 +08:00

192 lines
5.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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]
说明:
- 若未检测到仓库内 obsutil,会自动调用 lib/obsutil.sh 安装
- system 模式会安装到 /etc/systemd/system
- user 模式会安装到 ~/.config/systemd/user
- 会为目标用户安装每天 03:00 执行一次的备份 cron
- 安装完成后会执行一次 ./backup.sh --self-check 自检
- 不会覆盖已有 env.conf 和 exclude.user.list
- dry-run 只打印将执行的动作,不实际写入 systemd 或 crontab
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
need_cmd crontab
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
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"
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/obsutil.sh" \
"${SCRIPT_DIR}/lib/telegram.sh" \
"${SCRIPT_DIR}/install.sh" \
"${SCRIPT_DIR}/update.sh"
if [[ -f "${SCRIPT_DIR}/obsutil" ]]; then
chmod 755 "${SCRIPT_DIR}/obsutil"
fi
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"
install_backup_cron() {
local cron_line current_cron filtered_cron target_user current_user
cron_line="0 3 * * * ${SCRIPT_DIR}/backup.sh"
current_user="$(id -un)"
target_user="$INSTALL_USER"
if $DRY_RUN; then
echo "[dry-run] 将为用户 ${target_user} 写入 cron${cron_line}"
return 0
fi
if [[ "$(id -u)" -eq 0 ]]; then
current_cron="$(crontab -u "$target_user" -l 2>/dev/null || true)"
filtered_cron="$(printf '%s\n' "$current_cron" | grep -v -F "${SCRIPT_DIR}/backup.sh" || true)"
printf '%s\n%s\n' "$filtered_cron" "$cron_line" | sed '/^$/N;/^\n$/D' | crontab -u "$target_user" -
echo "已为用户 ${target_user} 安装 cron${cron_line}"
return 0
fi
if [[ "$target_user" != "$current_user" ]]; then
echo "非 root 模式下只能为当前用户 ${current_user} 安装 cron" >&2
exit 2
fi
current_cron="$(crontab -l 2>/dev/null || true)"
filtered_cron="$(printf '%s\n' "$current_cron" | grep -v -F "${SCRIPT_DIR}/backup.sh" || true)"
printf '%s\n%s\n' "$filtered_cron" "$cron_line" | sed '/^$/N;/^\n$/D' | crontab -
echo "已为当前用户安装 cron${cron_line}"
}
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 timerbackup-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 timerbackup-obs-update.timer"
echo "查看状态:systemctl --user status backup-obs-update.timer"
echo "查看日志:journalctl --user -u backup-obs-update.service -n 100"
fi
install_backup_cron
if $DRY_RUN; then
echo "[dry-run] 将执行 ./backup.sh --self-check"
else
bash "${SCRIPT_DIR}/backup.sh" --self-check
fi