#!/bin/bash # ============================================================ # 宿主部署链组件安装/升级(CMA) # cma-deploy-source-decouple-20260921(单 project-20260921-deploy-dirtyguard-rootfix) # # 把本仓 deploy/ 下的宿主侧组件安装到 /usr/local/sbin/(改前自动备份、改后校验 md5)。 # 组件(宿主侧,容器内 gitea post-receive → SSH forced-command 进入本仓库时执行): # gitea-cma-deploy-hook.sh → /usr/local/sbin/gitea-cma-deploy-hook.sh # cma-deploy-dirty-guard.sh → /usr/local/sbin/cma-deploy-dirty-guard.sh # # 用法: # bash deploy/install-host-deploy-hook.sh # 安装/升级(含备份 + 校验) # bash deploy/install-host-deploy-hook.sh --check # 只比对(不写任何文件) # # 说明: # - 备份目录 /root/backups/cma-deploy-source-decouple-/ # - 一行回滚: cp <备份目录>/<文件名> /usr/local/sbin/<文件名> && md5sum -c <备份目录>/MD5SUMS.rollback # ============================================================ set -euo pipefail REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)" SRC_DIR="$REPO_DIR/deploy" DST_DIR="/usr/local/sbin" FILES=(gitea-cma-deploy-hook.sh cma-deploy-dirty-guard.sh) MODE="${1:-install}" for f in "${FILES[@]}"; do [ -r "$SRC_DIR/$f" ] || { echo "❌ 源文件缺失: $SRC_DIR/$f"; exit 1; } done if [ "$MODE" = "--check" ]; then rc=0 for f in "${FILES[@]}"; do if [ -r "$DST_DIR/$f" ] && cmp -s "$SRC_DIR/$f" "$DST_DIR/$f"; then echo "✓ 一致: $DST_DIR/$f" else echo "≠ 不一致: $DST_DIR/$f(需要安装)"; rc=1 fi done exit "$rc" fi TS="$(date +%Y%m%d-%H%M%S)" BAK_DIR="/root/backups/cma-deploy-source-decouple-$TS" mkdir -p "$BAK_DIR" for f in "${FILES[@]}"; do if [ -e "$DST_DIR/$f" ]; then cp -a "$DST_DIR/$f" "$BAK_DIR/$f" md5sum "$DST_DIR/$f" >> "$BAK_DIR/MD5SUMS.rollback" else echo "" >> "$BAK_DIR/MD5SUMS.rollback" fi done for f in "${FILES[@]}"; do install -m 0755 -o root -g root "$SRC_DIR/$f" "$DST_DIR/$f" done echo "备份目录: $BAK_DIR" for f in "${FILES[@]}"; do echo "已安装: $DST_DIR/$f md5=$(md5sum "$DST_DIR/$f" | awk '{print $1}')" done bash -n "$DST_DIR/gitea-cma-deploy-hook.sh" && echo "✓ 语法检查通过" echo "✓ 安装完成(生效于下一次 push 触发的部署)"