238 lines
6.0 KiB
Bash
Executable File
238 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
# 一键把源码同步到开发机测试目录:Memind / memind_adm / Plaza
|
||
# 适用:更新基于源码的开发机器环境。goose 不在本流程内。
|
||
|
||
HOST="${DEPLOY_HOST:-192.168.1.9}"
|
||
USER="${DEPLOY_USER:-john}"
|
||
TARGET="${DEPLOY_USER_HOST:-${USER}@${HOST}}"
|
||
|
||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||
EXCLUDE_FILE="${ROOT_DIR}/scripts/.rsync-exclude-test-host"
|
||
|
||
MEMIND_SRC="${MEMIND_SRC:-${ROOT_DIR}}"
|
||
ADM_SRC="${ADM_SRC:-${ROOT_DIR}/../memind_adm}"
|
||
PLAZA_SRC="${PLAZA_SRC:-${ROOT_DIR}/../memind_plaza}"
|
||
|
||
MEMIND_DST="${MEMIND_DST:-/Users/john/Project/Memind}"
|
||
ADM_DST="${ADM_DST:-/Users/john/Project/memind_adm}"
|
||
PLAZA_DST="${PLAZA_DST:-/Users/john/Project/memind_plaza}"
|
||
|
||
RSYNC_OPTS=(
|
||
-az
|
||
--delete
|
||
--exclude-from="${EXCLUDE_FILE}"
|
||
)
|
||
|
||
DRY_RUN=0
|
||
CHECK_ONLY=0
|
||
ONLY_MEMIND=0
|
||
ONLY_ADM=0
|
||
ONLY_PLAZA=0
|
||
SKIP_MV=0
|
||
AUTO_YES=0
|
||
|
||
usage() {
|
||
cat <<USAGE
|
||
用法: ./scripts/deploy-to-test-host.sh [选项]
|
||
|
||
目标目录(支持环境变量覆盖)
|
||
DEPLOY_HOST, DEPLOY_USER, DEPLOY_USER_HOST
|
||
MEMIND_SRC, ADM_SRC, PLAZA_SRC
|
||
MEMIND_DST, ADM_DST, PLAZA_DST
|
||
MEMIND_STATUS_URL, ADMIN_STATUS_URL, PLAZA_URL
|
||
|
||
常用选项
|
||
--only-memind 仅同步 test-memind
|
||
--only-adm 仅同步 test-memindadm
|
||
--only-plaza 仅同步 test-memindplaza
|
||
--skip-delete 同步时不做 --delete(避免误删未排除文件)
|
||
--dry-run 预览变更,不实际写入
|
||
--check-only 只做连通性和目录检查,不做 rsync
|
||
--yes 非交互,自动确认
|
||
--help 显示帮助
|
||
|
||
示例
|
||
./scripts/deploy-to-test-host.sh --dry-run
|
||
./scripts/deploy-to-test-host.sh --only-memind --skip-delete
|
||
USAGE
|
||
}
|
||
|
||
while [[ "$#" -gt 0 ]]; do
|
||
case "$1" in
|
||
--only-memind) ONLY_MEMIND=1 ;;
|
||
--only-adm) ONLY_ADM=1 ;;
|
||
--only-plaza) ONLY_PLAZA=1 ;;
|
||
--skip-delete) SKIP_MV=1 ;;
|
||
--dry-run) DRY_RUN=1 ;;
|
||
--check-only) CHECK_ONLY=1 ;;
|
||
--yes) AUTO_YES=1 ;;
|
||
--help|-h)
|
||
usage
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo "未知参数: $1" >&2
|
||
usage
|
||
exit 1
|
||
;;
|
||
esac
|
||
shift
|
||
done
|
||
|
||
if [[ "${ONLY_MEMIND}" -eq 1 && ("${ONLY_ADM}" -eq 1 || "${ONLY_PLAZA}" -eq 1) ]] ||
|
||
[[ "${ONLY_ADM}" -eq 1 && "${ONLY_PLAZA}" -eq 1 ]]; then
|
||
echo "错误: --only-* 只能选一个" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [[ "${SKIP_MV}" -eq 1 ]]; then
|
||
RSYNC_OPTS=(
|
||
-az
|
||
--exclude-from="${EXCLUDE_FILE}"
|
||
)
|
||
fi
|
||
|
||
if [[ ! -f "${EXCLUDE_FILE}" ]]; then
|
||
echo "错误: 未找到排除规则文件 ${EXCLUDE_FILE}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
SSH_OPTS=(-o BatchMode=yes -o ConnectTimeout=12)
|
||
|
||
log() { printf '%s\n' "$*"; }
|
||
err() { printf '%s\n' "$*" >&2; }
|
||
fail() { err "✗ $*"; exit 1; }
|
||
ok() { printf '%s\n' "✓ $*"; }
|
||
|
||
ssh_to_host() {
|
||
ssh "${SSH_OPTS[@]}" "${TARGET}" "$*"
|
||
}
|
||
|
||
preflight_local() {
|
||
local src=$1
|
||
[[ -d "$src" ]] || fail "本地源目录不存在: $src"
|
||
[[ -f "$src/.gitignore" ]] || true
|
||
ok "本地源目录存在: $src"
|
||
}
|
||
|
||
preflight_remote() {
|
||
local dst=$1
|
||
local label=$2
|
||
ssh_to_host "mkdir -p '${dst}'" >/dev/null
|
||
if ! ssh_to_host "test -w '${dst}'" >/dev/null 2>&1; then
|
||
fail "远端目标不可写: ${label} -> ${TARGET}:${dst}"
|
||
fi
|
||
ok "远端目录可写: ${label} -> ${dst}"
|
||
}
|
||
|
||
ensure_host() {
|
||
log "检查 SSH: ${TARGET}"
|
||
ssh_to_host "echo connected" >/dev/null || fail "SSH 连接失败:${TARGET}"
|
||
ok "SSH 连接成功: ${TARGET}"
|
||
}
|
||
|
||
need_confirm() {
|
||
local target=$1
|
||
[[ "${AUTO_YES}" -eq 1 ]] && return 0
|
||
read -r -p "确认同步 ${target}?[y/N] " input
|
||
[[ "$input" == "y" || "$input" == "Y" ]]
|
||
}
|
||
|
||
do_sync() {
|
||
local label=$1
|
||
local src=$2
|
||
local dst=$3
|
||
local flags=("${RSYNC_OPTS[@]}")
|
||
|
||
preflight_local "$src"
|
||
preflight_remote "$dst" "$label"
|
||
|
||
if [[ "${DRY_RUN}" -eq 1 ]]; then
|
||
flags+=(--dry-run --itemize-changes)
|
||
log "[预览] ${label}: ${src} -> ${TARGET}:${dst}"
|
||
rsync "${flags[@]}" "${src}/" "${TARGET}:${dst}/" | head -80
|
||
return 0
|
||
fi
|
||
|
||
if ! need_confirm "$label"; then
|
||
fail "用户取消:${label}"
|
||
fi
|
||
|
||
log "同步中 ${label}: ${src} -> ${TARGET}:${dst}"
|
||
rsync "${flags[@]}" "${src}/" "${TARGET}:${dst}/"
|
||
ok "同步完成 ${label}"
|
||
}
|
||
|
||
health_check() {
|
||
local label=$1
|
||
local url=$2
|
||
|
||
if [[ -z "${url}" ]]; then
|
||
return 0
|
||
fi
|
||
|
||
if ssh_to_host "command -v curl >/dev/null && curl -fsS '${url}' >/dev/null" >/dev/null 2>&1; then
|
||
ok "${label} 健康检查通过:${url}"
|
||
else
|
||
log "⚠ ${label} 健康检查失败:${url}(仅提示)"
|
||
fi
|
||
}
|
||
|
||
export MEMIND_STATUS_URL="${MEMIND_STATUS_URL:-http://127.0.0.1:18081/api/status}"
|
||
export ADMIN_STATUS_URL="${ADMIN_STATUS_URL:-http://127.0.0.1:18082/healthz}"
|
||
export PLAZA_URL="${PLAZA_URL:-http://127.0.0.1:13001/plaza}"
|
||
|
||
ensure_host
|
||
|
||
if [[ "${CHECK_ONLY}" -eq 1 ]]; then
|
||
preflight_remote "${MEMIND_DST}" "Memind"
|
||
preflight_remote "${ADM_DST}" "memind_adm"
|
||
preflight_remote "${PLAZA_DST}" "Plaza"
|
||
ok "检查通过:远端目录可用"
|
||
health_check "Memind" "${MEMIND_STATUS_URL}"
|
||
health_check "memind_adm" "${ADMIN_STATUS_URL}"
|
||
health_check "Plaza" "${PLAZA_URL}"
|
||
exit 0
|
||
fi
|
||
|
||
TARGETS=()
|
||
if [[ "${ONLY_MEMIND}" -eq 1 ]]; then
|
||
TARGETS+=("memind")
|
||
elif [[ "${ONLY_ADM}" -eq 1 ]]; then
|
||
TARGETS+=("adm")
|
||
elif [[ "${ONLY_PLAZA}" -eq 1 ]]; then
|
||
TARGETS+=("plaza")
|
||
else
|
||
TARGETS+=("memind" "adm" "plaza")
|
||
fi
|
||
|
||
for t in "${TARGETS[@]}"; do
|
||
case "$t" in
|
||
memind)
|
||
do_sync "Memind" "${MEMIND_SRC}" "${MEMIND_DST}"
|
||
;;
|
||
adm)
|
||
do_sync "memind_adm" "${ADM_SRC}" "${ADM_DST}"
|
||
;;
|
||
plaza)
|
||
do_sync "Plaza" "${PLAZA_SRC}" "${PLAZA_DST}"
|
||
;;
|
||
esac
|
||
done
|
||
|
||
log "同步完成。建议检查:"
|
||
log " Memind: ${MEMIND_STATUS_URL}"
|
||
log " memind_adm: ${ADMIN_STATUS_URL}"
|
||
log " Plaza: ${PLAZA_URL}"
|
||
|
||
echo "\n可在远端执行 restart(不包含 goose)"
|
||
echo " ssh ${TARGET}"
|
||
echo " cd ${MEMIND_DST} && pnpm install && pnpm dev:server 或 pm2 reload memind"
|
||
echo " cd ${ADM_DST} && pnpm install && pnpm start:??"
|
||
echo " cd ${PLAZA_DST} && pnpm install && pnpm dev:plaza"
|
||
|
||
echo ""
|
||
echo "如果需要,我也可以把 restart 命令固定成你们当前启动脚架构(例如 launchctl/systemd/pm2/nodemon)。"
|