Files
Nexus/deploy/nx
T
Nexus Deploy 1bd69077a2 fix(deploy): auto-remove legacy Compose MySQL containers on upgrade
Run uninstall-mysql-compose before install/upgrade and pass --remove-orphans so nexus-prod mysql orphans are stopped after the service is dropped from compose.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 03:32:00 +08:00

388 lines
12 KiB
Bash
Raw 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
# Nexus NX — 一键安装 + 上帝菜单(1Panel Docker 生产栈)
#
# bash deploy/nx 交互菜单
# bash deploy/nx install 同菜单「安装」
# bash deploy/nx god 上帝菜单(运维)
# nx 安装后链到 /usr/local/bin/nx
#
set -euo pipefail
# 经 /usr/local/bin/nx 符号链接调用时,须 readlink 才能找到 deploy/ 目录
NX_SELF="$(readlink -f "${BASH_SOURCE[0]}")"
NX_DIR="$(cd "$(dirname "$NX_SELF")" && pwd)"
# shellcheck source=./nexus-1panel.sh
source "${NX_DIR}/nexus-1panel.sh"
pause_enter() {
echo ""
read -r -p "按 Enter 继续..."
}
clear_screen() {
if [[ -t 1 ]]; then
clear 2>/dev/null || true
fi
}
is_stack_installed() {
[[ -d "${NEXUS_ROOT}/.git" && -f "${NEXUS_ROOT}/${ENV_PROD}" ]]
}
detect_runtime() {
if is_stack_installed && docker compose version >/dev/null 2>&1; then
local prof q
prof="$(profile_env_file "$NEXUS_ROOT")"
if [[ -f "$prof" && -f "$NEXUS_ROOT/$ENV_PROD" ]]; then
q="$(cd "$NEXUS_ROOT" && docker compose -f "$COMPOSE_FILE" \
--env-file "$ENV_PROD" --env-file "$prof" ps -q nexus 2>/dev/null || true)"
if [[ -n "$q" ]]; then
NX_RUNTIME="docker"
return 0
fi
fi
fi
if command -v supervisorctl >/dev/null 2>&1 && supervisorctl status nexus >/dev/null 2>&1; then
NX_RUNTIME="supervisor"
return 0
fi
NX_RUNTIME="none"
}
install_nx_cli() {
if [[ "$(id -u)" -ne 0 ]]; then
return 0
fi
ln -sf "${NX_DIR}/nx" /usr/local/bin/nx 2>/dev/null || true
chmod +x "${NX_DIR}/nx" 2>/dev/null || true
}
menu_header() {
local title="$1"
clear_screen
echo ""
echo "╔══════════════════════════════════════════════════════════╗"
echo "║ Nexus NX — ${title}"
echo "╠══════════════════════════════════════════════════════════╣"
echo "║ 域名: ${NEXUS_DOMAIN} 目录: ${NEXUS_ROOT}"
if is_stack_installed; then
detect_runtime
echo "║ 运行: ${NX_RUNTIME} 档位: $(cat "${NEXUS_ROOT}/${HOST_PROFILE_FILE}" 2>/dev/null || echo "${NEXUS_PROFILE}")"
if [[ -d "${NEXUS_ROOT}/.git" ]]; then
echo "║ 版本: $(git -C "${NEXUS_ROOT}" log -1 --oneline 2>/dev/null || echo '?')"
fi
else
echo "║ 状态: 未安装"
fi
echo "╚══════════════════════════════════════════════════════════╝"
echo ""
}
run_install() {
local profile="${1:-2c8g}" extra="${2:-}"
NEXUS_PROFILE="$profile"
SKIP_CLONE=false
FRESH_INSTALL=false
NO_BACKUP=false
PRUNE_IMAGES=false
FROM_ENV="${NEXUS_FROM_ENV}"
case "$extra" in
skip-clone) SKIP_CLONE=true ;;
fresh) FRESH_INSTALL=true ;;
from-env) FROM_ENV="${NEXUS_FROM_ENV}" ;;
esac
load_secrets
cmd_install
install_nx_cli
pause_enter
}
menu_install() {
while true; do
menu_header "安装向导"
cat <<'EOF'
[1] 一键安装(默认 2核8G / 2c8g)
[2] 安装 — 4核16G4c16g
[3] 安装 — 1核4G1c4g
[4] 自定义规格(输入 CPU 与内存 GB)
[5] 已 clone 到 /opt/nexus,仅 pull + 启动(--skip-clone
[6] 全新安装(install-nexus-fresh.sh → /app/install.html
[7] 检查端口 / 防火墙(不安装)
[8] 写入 Gitea 令牌(init-token
[9] 返回主菜单
[0] 退出
EOF
read -r -p "请选择: " choice
case "$choice" in
1) run_install 2c8g "" ;;
2) run_install 4c16g "" ;;
3) run_install 1c4g "" ;;
4)
read -r -p "CPU 核数: " cpus
read -r -p "内存 GB: " mem
CUSTOM_CPUS="$cpus"
CUSTOM_MEM_GB="$mem"
run_install 2c8g ""
;;
5) run_install 2c8g skip-clone ;;
6)
if [[ -x "${NX_DIR}/install-nexus-fresh.sh" ]]; then
bash "${NX_DIR}/install-nexus-fresh.sh" --profile "${NEXUS_PROFILE:-2c8g}"
else
run_install 2c8g fresh
fi
;;
7)
require_root
load_secrets
check_ports_preflight "$NEXUS_ROOT"
if is_stack_installed; then
check_ports_post "$NEXUS_ROOT"
fi
pause_enter
;;
8)
read -r -p "Gitea Access Token: " tok
cmd_init_token "$tok"
pause_enter
;;
9) return 0 ;;
0) exit 0 ;;
*) warn "无效选项" ; sleep 1 ;;
esac
done
}
god_restart_nexus() {
step "重启 NexusPython..."
if [[ "$NX_RUNTIME" == "docker" ]]; then
compose_cmd "$NEXUS_ROOT" restart nexus
elif [[ "$NX_RUNTIME" == "supervisor" ]]; then
supervisorctl restart nexus
else
error "未检测到运行中的 Nexus"
return 1
fi
info "已发送重启"
sleep 3
curl -sf "http://127.0.0.1:$(nexus_publish_port "$NEXUS_ROOT")/health" && info "/health → ok" || warn "健康检查未通过,请查看日志"
}
god_restart_stack() {
step "重启全部 Compose 服务..."
compose_cmd "$NEXUS_ROOT" restart
sleep 5
verify_health "$NEXUS_ROOT" "重启" || true
}
god_stop_stack() {
warn "将停止 Nexus 容器(MySQL/Redis 为外置服务,不受影响)"
read -r -p "确认? [y/N]: " c
[[ "$c" == "y" || "$c" == "Y" ]] || return 0
compose_cmd "$NEXUS_ROOT" stop
info "已停止"
}
god_start_stack() {
compose_cmd "$NEXUS_ROOT" up -d --remove-orphans
verify_health "$NEXUS_ROOT" "启动" || true
}
god_logs() {
local svc="${1:-nexus}"
echo ""
read -r -p "跟踪日志行数 [80]: " n
n="${n:-80}"
compose_cmd "$NEXUS_ROOT" logs --tail="$n" -f "$svc"
}
god_status() {
if [[ "$NX_RUNTIME" == "docker" ]]; then
compose_cmd "$NEXUS_ROOT" ps
elif [[ "$NX_RUNTIME" == "supervisor" ]]; then
supervisorctl status nexus
fi
echo ""
local port h
port="$(nexus_publish_port "$NEXUS_ROOT")"
h=$(curl -sf "http://127.0.0.1:${port}/health" 2>/dev/null || echo "fail")
info "/health → ${h}"
curl -s -o /dev/null -w " /app/ HTTP %{http_code}\n" "http://127.0.0.1:${port}/app/" 2>/dev/null || true
}
god_backup_now() {
NO_BACKUP=false
backup_mysql "$NEXUS_ROOT"
}
god_upgrade_interactive() {
PRUNE_IMAGES=false
NO_BACKUP=false
read -r -p "跳过 MySQL 备份? [y/N]: " nb
[[ "$nb" == "y" || "$nb" == "Y" ]] && NO_BACKUP=true
read -r -p "升级后清理悬空镜像? [y/N]: " pr
[[ "$pr" == "y" || "$pr" == "Y" ]] && PRUNE_IMAGES=true
cmd_upgrade
pause_enter
}
menu_god() {
if ! is_stack_installed; then
warn "尚未安装,请先使用安装向导"
pause_enter
return 0
fi
require_root
load_secrets
load_saved_profile "$NEXUS_ROOT"
detect_runtime
while true; do
menu_header "上帝菜单 · 运维"
cat <<EOF
── 服务 ──
[1] 重启 NexusPython 应用)
[2] 重启 Compose 栈(仅 Nexus 容器)
[3] 启动 Compose 栈
[4] 停止 Compose 栈
[5] 重建 Nexus 镜像并启动(up -d --build nexus
── 观测 ──
[6] 状态 + 健康检查
[7] 查看 Nexus 日志(跟踪)
[8] 查看 Nexus 日志(备用入口)
[9] 端口 / 防火墙检查
── 发布 ──
[a] 检查 Git 更新
[b] 一键升级(备份 + pull + 重建)
[c] 立即备份 MySQL
── 其他 ──
[d] 进入 Nexus 容器 shell
[e] 打开 1Panel 反代说明
[0] 返回主菜单
EOF
read -r -p "请选择: " choice
case "$choice" in
1) god_restart_nexus; pause_enter ;;
2) god_restart_stack; pause_enter ;;
3) god_start_stack; pause_enter ;;
4) god_stop_stack; pause_enter ;;
5)
compose_cmd "$NEXUS_ROOT" up -d --build --remove-orphans nexus
verify_health "$NEXUS_ROOT" "重建" || true
pause_enter
;;
6) god_status; pause_enter ;;
7) god_logs nexus ;;
8) god_logs nexus ;;
9)
check_ports_preflight "$NEXUS_ROOT"
check_ports_post "$NEXUS_ROOT"
pause_enter
;;
a|A)
cmd_check
pause_enter
;;
b|B) god_upgrade_interactive ;;
c|C) god_backup_now; pause_enter ;;
d)
compose_cmd "$NEXUS_ROOT" exec nexus bash || compose_cmd "$NEXUS_ROOT" exec nexus sh
;;
e)
info "1Panel → 网站 → 创建站点 ${NEXUS_DOMAIN}"
info "反向代理: http://127.0.0.1:$(nexus_publish_port "$NEXUS_ROOT")"
info "示例配置: ${NEXUS_ROOT}/deploy/1panel/openresty-nexus.conf.example"
pause_enter
;;
0) return 0 ;;
*) warn "无效选项"; sleep 1 ;;
esac
done
}
menu_main() {
load_secrets
while true; do
menu_header "主菜单"
if is_stack_installed; then
echo " 提示: 安装完成后请用 [2] 上帝菜单 重启 Python / 升级 / 看日志"
echo ""
fi
cat <<'EOF'
[1] 安装向导(新机 / 迁机)
[2] 上帝菜单(重启 Python · 升级 · 日志 · 备份)
[3] 快速健康检查
[0] 退出
EOF
read -r -p "请选择: " choice
case "$choice" in
1) menu_install ;;
2) menu_god ;;
3)
require_root
if is_stack_installed; then
god_status
else
check_ports_preflight "$NEXUS_ROOT"
fi
pause_enter
;;
0) exit 0 ;;
*) warn "无效选项"; sleep 1 ;;
esac
done
}
nx_main() {
local sub="${1:-}"
load_secrets
case "$sub" in
""|menu) menu_main ;;
install) menu_install ;;
god|ops|admin) menu_god ;;
install-fresh|fresh)
require_root
exec bash "${NX_DIR}/install-nexus-fresh.sh" "$@"
;;
install-auto|auto)
require_root
if is_stack_installed; then
run_install "${NEXUS_PROFILE:-2c8g}" skip-clone
else
run_install "${NEXUS_PROFILE:-2c8g}" ""
fi
;;
health)
require_root
is_stack_installed && god_status || check_ports_preflight "$NEXUS_ROOT"
;;
-h|--help)
cat <<EOF
用法: nx [子命令]
(无) 交互主菜单
install 安装向导
install-fresh 全新安装(1Panel 风格,/app/install.html
install-auto 非交互安装已有密钥(2c8g)
god 上帝菜单(重启/升级/日志)
health 健康检查
底层仍可使用: bash deploy/nexus-1panel.sh install|upgrade|check|ports
EOF
;;
*)
# 兼容 nexus-1panel.sh 子命令
main "$@"
;;
esac
}
chmod +x "${NX_DIR}/nx" 2>/dev/null || true
nx_main "$@"