1714732b10
Co-authored-by: Cursor <cursoragent@cursor.com>
223 lines
6.2 KiB
Bash
223 lines
6.2 KiB
Bash
#!/usr/bin/env bash
|
||
# gold_monitor 部署管理器 — 一键部署 / 卸载 / 更新
|
||
#
|
||
# 新服务器(免克隆):
|
||
# curl -fsSL https://git.bz121.com/dekun/gold_monitor/raw/branch/main/deploy/manage.sh | bash
|
||
#
|
||
# 已安装(推荐,可交互):
|
||
# bash /opt/gold_monitor/deploy/manage.sh
|
||
#
|
||
# 非交互快速更新:
|
||
# bash /opt/gold_monitor/deploy/manage.sh update
|
||
# curl -fsSL .../deploy/manage.sh | bash -s -- update
|
||
#
|
||
set -e
|
||
if [ -n "${BASH_VERSION:-}" ]; then
|
||
set -o pipefail
|
||
fi
|
||
|
||
INSTALL_ROOT="${INSTALL_ROOT:-/opt/gold_monitor}"
|
||
GIT_URL="${GIT_URL:-https://git.bz121.com/dekun/gold_monitor.git}"
|
||
GIT_BRANCH="${GIT_BRANCH:-main}"
|
||
|
||
_script_src="${BASH_SOURCE[0]:-}"
|
||
if [[ -n "${_script_src}" && -f "${_script_src}" ]]; then
|
||
DEPLOY_DIR="$(cd "$(dirname "${_script_src}")" && pwd)"
|
||
REPO_ROOT="$(cd "${DEPLOY_DIR}/.." && pwd)"
|
||
LIB_DIR="${DEPLOY_DIR}/lib"
|
||
else
|
||
# curl | bash 时脚本从 stdin 执行,无本地路径
|
||
DEPLOY_DIR=""
|
||
REPO_ROOT=""
|
||
LIB_DIR=""
|
||
fi
|
||
unset _script_src
|
||
|
||
set -u
|
||
|
||
repo_ready() {
|
||
[[ -f "${1}/deploy/setup_env.sh" && -f "${1}/deploy/manage.sh" ]]
|
||
}
|
||
|
||
sync_repo_if_present() {
|
||
local root="$1"
|
||
if [[ -d "${root}/.git" ]] && command -v git >/dev/null 2>&1; then
|
||
git -C "${root}" pull -q --ff-only 2>/dev/null || true
|
||
fi
|
||
}
|
||
|
||
bootstrap_repo() {
|
||
if repo_ready "${INSTALL_ROOT}"; then
|
||
REPO_ROOT="${INSTALL_ROOT}"
|
||
DEPLOY_DIR="${REPO_ROOT}/deploy"
|
||
LIB_DIR="${DEPLOY_DIR}/lib"
|
||
sync_repo_if_present "${REPO_ROOT}"
|
||
return 0
|
||
fi
|
||
if [[ -n "${REPO_ROOT}" ]] && repo_ready "${REPO_ROOT}"; then
|
||
DEPLOY_DIR="${REPO_ROOT}/deploy"
|
||
LIB_DIR="${DEPLOY_DIR}/lib"
|
||
return 0
|
||
fi
|
||
|
||
echo "gold_monitor 部署管理器 — 首次自举"
|
||
echo "将克隆到: ${INSTALL_ROOT}"
|
||
if [[ "$(id -u)" -ne 0 ]]; then
|
||
echo "错误: 请使用 root 执行" >&2
|
||
exit 1
|
||
fi
|
||
if ! command -v git >/dev/null 2>&1; then
|
||
if command -v apt-get >/dev/null 2>&1; then
|
||
export DEBIAN_FRONTEND=noninteractive
|
||
apt-get update -qq
|
||
apt-get install -y git ca-certificates curl
|
||
else
|
||
echo "错误: 未找到 git" >&2
|
||
exit 1
|
||
fi
|
||
fi
|
||
if [[ -d "${INSTALL_ROOT}" ]]; then
|
||
echo "错误: ${INSTALL_ROOT} 已存在但不是有效仓库" >&2
|
||
exit 1
|
||
fi
|
||
mkdir -p "$(dirname "${INSTALL_ROOT}")"
|
||
git clone -b "${GIT_BRANCH}" "${GIT_URL}" "${INSTALL_ROOT}"
|
||
exec bash "${INSTALL_ROOT}/deploy/manage.sh" "$@" </dev/tty >/dev/tty 2>/dev/tty
|
||
}
|
||
|
||
# curl|bash 时 stdin 是脚本管道,菜单 read 会立刻 EOF;挂到真实终端
|
||
attach_tty() {
|
||
# 把 0/1/2 都接到控制终端,避免只重定向 stdin 后 read 仍异常
|
||
if [[ -e /dev/tty ]]; then
|
||
exec </dev/tty >/dev/tty 2>/dev/tty
|
||
fi
|
||
}
|
||
|
||
ensure_interactive_tty() {
|
||
if [[ -t 0 ]]; then
|
||
return 0
|
||
fi
|
||
local local_mgr="${INSTALL_ROOT}/deploy/manage.sh"
|
||
if [[ -n "${REPO_ROOT}" && -f "${REPO_ROOT}/deploy/manage.sh" ]]; then
|
||
local_mgr="${REPO_ROOT}/deploy/manage.sh"
|
||
fi
|
||
|
||
# 1) 同进程直接挂接 /dev/tty(不二次启动,少一层「像故障」的提示)
|
||
if [[ -e /dev/tty ]] && attach_tty 2>/dev/null && [[ -t 0 ]]; then
|
||
echo "已挂接本机终端,请继续选择。"
|
||
return 0
|
||
fi
|
||
|
||
# 2) 回退:用本机已安装脚本重新 exec(stdin/stdout/stderr 全挂 tty)
|
||
if [[ -e /dev/tty && -f "${local_mgr}" ]]; then
|
||
echo "改用本机管理器启动: ${local_mgr}"
|
||
exec bash "${local_mgr}" "$@" </dev/tty >/dev/tty 2>/dev/tty
|
||
fi
|
||
|
||
echo "错误: 当前没有可用交互终端(curl|bash 的管道不能读菜单)。" >&2
|
||
echo "请改用:" >&2
|
||
echo " bash ${INSTALL_ROOT}/deploy/manage.sh" >&2
|
||
echo " bash ${INSTALL_ROOT}/deploy/manage.sh update" >&2
|
||
echo " curl -fsSL https://git.bz121.com/dekun/gold_monitor/raw/branch/main/deploy/manage.sh | bash -s -- update" >&2
|
||
exit 1
|
||
}
|
||
|
||
read_menu_choice() {
|
||
# set -e 下 read 遇 EOF 会直接退出,这里显式处理
|
||
local choice=""
|
||
if ! IFS= read -r -p "请选择: " choice </dev/tty; then
|
||
echo "" >&2
|
||
echo "错误: 读不到键盘输入(终端未挂接成功)。" >&2
|
||
echo "请直接执行: bash ${INSTALL_ROOT}/deploy/manage.sh" >&2
|
||
exit 1
|
||
fi
|
||
# 去掉 Windows 粘贴带来的 \\r
|
||
choice="${choice//$'\r'/}"
|
||
printf '%s' "${choice}"
|
||
}
|
||
|
||
run_update_quick() {
|
||
export REPO_ROOT DEPLOY_DIR LIB_DIR INSTALL_ROOT GIT_URL GIT_BRANCH
|
||
# shellcheck source=/dev/null
|
||
source "${LIB_DIR}/common.sh"
|
||
need_root
|
||
echo "快速更新: git pull + pm2 restart"
|
||
git -C "${REPO_ROOT}" pull --ff-only
|
||
pm2 restart gold_monitor
|
||
echo "更新完成"
|
||
}
|
||
|
||
show_banner() {
|
||
local ip path
|
||
path="${INSTALL_ROOT}"
|
||
if repo_ready "${REPO_ROOT}"; then
|
||
path="${REPO_ROOT}"
|
||
fi
|
||
if [[ -f "${LIB_DIR}/common.sh" ]]; then
|
||
# shellcheck source=/dev/null
|
||
source "${LIB_DIR}/common.sh"
|
||
ip="$(detect_server_ip)"
|
||
else
|
||
ip="?"
|
||
fi
|
||
echo ""
|
||
echo "╔══════════════════════════════════════╗"
|
||
echo "║ gold_monitor 部署管理器 ║"
|
||
echo "║ 路径: ${path}"
|
||
echo "║ 端口: 5800 IP: ${ip}"
|
||
echo "╚══════════════════════════════════════╝"
|
||
echo ""
|
||
}
|
||
|
||
show_menu() {
|
||
echo " 1) 一键部署(Web + API + PM2)"
|
||
echo " 2) 一键卸载"
|
||
echo " 3) 更新"
|
||
echo " 0) 退出"
|
||
echo ""
|
||
}
|
||
|
||
main_menu() {
|
||
bootstrap_repo "$@"
|
||
export REPO_ROOT DEPLOY_DIR LIB_DIR INSTALL_ROOT GIT_URL GIT_BRANCH
|
||
|
||
local cmd="${1:-}"
|
||
case "${cmd}" in
|
||
update|3)
|
||
# shellcheck source=/dev/null
|
||
source "${LIB_DIR}/common.sh"
|
||
run_update_quick
|
||
exit 0
|
||
;;
|
||
update-deps)
|
||
# shellcheck source=/dev/null
|
||
source "${LIB_DIR}/common.sh"
|
||
need_root
|
||
git -C "${REPO_ROOT}" pull --ff-only
|
||
bash "${REPO_ROOT}/deploy/setup_env.sh"
|
||
pm2 restart gold_monitor
|
||
echo "依赖更新完成"
|
||
exit 0
|
||
;;
|
||
esac
|
||
|
||
ensure_interactive_tty "$@"
|
||
# shellcheck source=/dev/null
|
||
source "${LIB_DIR}/common.sh"
|
||
show_banner
|
||
while true; do
|
||
show_menu
|
||
choice="$(read_menu_choice)"
|
||
case "${choice}" in
|
||
1) bash "${LIB_DIR}/install.sh" ;;
|
||
2) bash "${LIB_DIR}/uninstall.sh" ;;
|
||
3) bash "${LIB_DIR}/update.sh" ;;
|
||
0) exit 0 ;;
|
||
*) echo "无效选项: ${choice:-"(空)"}" ;;
|
||
esac
|
||
echo ""
|
||
done
|
||
}
|
||
|
||
main_menu "$@"
|