#!/bin/bash # deploy.sh — 一键部署到树莓派 + 云服务器 # # 用法: # ./deploy.sh 构建并部署到两个目标(生产环境会先确认) # ./deploy.sh -y 跳过确认 # ./deploy.sh --pi-only 只部署树莓派(内网预览) # ./deploy.sh --cloud-only 只部署云服务器 # ./deploy.sh --skip-build 不重新构建,直接推送现有 dist/ # ./deploy.sh --dry-run 只显示 rsync 会做什么,不实际写入 set -euo pipefail # ========== 配置区(按需修改) ========== PI_HOST="192.168.1.87" # 树莓派 IP PI_USER="pi" PI_SITE_PATH="/home/pi/www/Astro_vermilion/" # 与 Firefly 分开放,方便对比 CLOUD_HOST="81.70.45.191" # 云服务器 IP CLOUD_USER="root" CLOUD_KEY="$HOME/.ssh/Astro.pem" # 云服务器 SSH 密钥 CLOUD_SITE_PATH="/opt/1panel/apps/caddy/caddy/data/srv/astro-blog/" # Caddy 站点目录 CLOUD_URL="http://81.70.45.191:3500" # ======================================== cd "$(dirname "$0")" DO_PI=1 DO_CLOUD=1 SKIP_BUILD=0 DRY_RUN=0 ASSUME_YES=0 for arg in "$@"; do case "$arg" in --pi-only) DO_CLOUD=0 ;; --cloud-only) DO_PI=0 ;; --skip-build) SKIP_BUILD=1 ;; --dry-run) DRY_RUN=1 ;; -y|--yes) ASSUME_YES=1 ;; -h|--help) sed -n '2,10p' "$0" | sed 's/^# \{0,1\}//' exit 0 ;; *) echo "⚠️ 忽略未知参数: $arg" ;; esac done if [ "$DO_PI" -eq 0 ] && [ "$DO_CLOUD" -eq 0 ]; then echo "❌ 两个目标都被关掉了,无事可做" exit 1 fi # ---------- 1. 构建 ---------- if [ "$SKIP_BUILD" -eq 0 ]; then echo "🔨 构建中..." # 关键:构建失败必须中止。否则会拿着残缺或过期的 dist/ 执行 rsync --delete, # 把线上站点删空。 if ! pnpm build; then echo "" echo "❌ 构建失败,已中止部署(没有推送任何内容)" exit 1 fi else echo "⏭ 跳过构建(--skip-build)" fi # ---------- 2. 产物自检 ---------- if [ ! -f dist/index.html ]; then echo "❌ dist/index.html 不存在,构建产物异常,已中止" echo " (rsync --delete 会用它清空线上目录,所以这里必须拦住)" exit 1 fi PAGES=$(find dist -name '*.html' | wc -l) SIZE=$(du -sh dist | cut -f1) echo "✅ 构建产物:$PAGES 个页面,共 $SIZE" if [ "$PAGES" -lt 5 ]; then echo "⚠️ 页面数只有 $PAGES,看起来不像一次正常构建。" if [ "$ASSUME_YES" -eq 0 ]; then read -r -p " 仍要继续吗?[y/N] " reply case "$reply" in [yY]*) ;; *) echo "已取消"; exit 1 ;; esac fi fi # ---------- 3. 生产环境确认 ---------- if [ "$DO_CLOUD" -eq 1 ] && [ "$DRY_RUN" -eq 0 ] && [ "$ASSUME_YES" -eq 0 ]; then echo "" echo "⚠️ 即将用 --delete 覆盖云服务器目录(这是你的线上站点):" echo " $CLOUD_USER@$CLOUD_HOST:$CLOUD_SITE_PATH" read -r -p " 确认部署?[y/N] " reply case "$reply" in [yY]*) ;; *) echo "已取消"; exit 1 ;; esac fi RSYNC_FLAGS=(-avz --delete) [ "$DRY_RUN" -eq 1 ] && RSYNC_FLAGS+=(--dry-run) && echo "🔍 dry-run:只显示将要同步的内容" FAIL=0 # ---------- 4. 树莓派 ---------- if [ "$DO_PI" -eq 1 ]; then echo "" echo "📦 推送到树莓派 ($PI_USER@$PI_HOST)" if rsync "${RSYNC_FLAGS[@]}" dist/ "$PI_USER@$PI_HOST:$PI_SITE_PATH"; then echo "✅ 树莓派部署完成: http://$PI_HOST" else echo "❌ 树莓派部署失败" FAIL=1 fi fi # ---------- 5. 云服务器 ---------- if [ "$DO_CLOUD" -eq 1 ]; then echo "" echo "📦 推送到云服务器 ($CLOUD_USER@$CLOUD_HOST)" if rsync "${RSYNC_FLAGS[@]}" -e "ssh -i $CLOUD_KEY" \ dist/ "$CLOUD_USER@$CLOUD_HOST:$CLOUD_SITE_PATH"; then echo "✅ 云服务器部署完成: $CLOUD_URL" else echo "❌ 云服务器部署失败" FAIL=1 fi fi echo "" if [ "$FAIL" -eq 0 ]; then [ "$DRY_RUN" -eq 1 ] && echo "🔍 dry-run 结束,没有实际改动。" || echo "🎉 全部部署完成!" else echo "⚠️ 有目标部署失败,请检查上面的报错信息。" exit 1 fi