Files
2026-10-21 16:35:22 +08:00

223 lines
6.2 KiB
Bash
Raw Permalink 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
# 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 "$@"