Files
Nexus/deploy/nx
T
2026-07-08 22:31:31 +08:00

453 lines
14 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 — 统一运维菜单(安装 + 升级 + 日常运维)
#
# nx 交互菜单
# nx update 一键更新(等同 deploy/update.sh
# nx update --no-cache 无缓存重建镜像
# nx install-fresh 全新安装
# nx health 健康检查
#
set -euo pipefail
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
local -a det_args=(-f "$COMPOSE_FILE")
if has_1panel_network && [[ -f "$NEXUS_ROOT/$COMPOSE_1PANEL" ]]; then
det_args+=(-f "$COMPOSE_1PANEL")
fi
q="$(cd "$NEXUS_ROOT" && docker compose "${det_args[@]}" \
--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() {
NEXUS_ROOT="$(cd "${NX_DIR}/.." && pwd)" \
bash "${NX_DIR}/install-nx-cli.sh" 2>/dev/null || true
}
menu_header() {
local title="$1"
clear_screen
echo ""
echo "╔══════════════════════════════════════════════════════════╗"
printf "║ Nexus NX — %-44s║\n" "$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] 检查端口 / 防火墙(不安装)
[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
;;
0) return 0 ;;
*) warn "无效选项" ; sleep 1 ;;
esac
done
}
ops_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
sleep 3
verify_health "$NEXUS_ROOT" "重启" || true
}
ops_restart_stack() {
step "重启 Compose 栈..."
compose_cmd "$NEXUS_ROOT" restart
sleep 5
verify_health "$NEXUS_ROOT" "重启" || true
}
ops_stop_stack() {
warn "将停止 Nexus 容器(MySQL/Redis 为外置服务,不受影响)"
read -r -p "确认? [y/N]: " c
[[ "$c" == "y" || "$c" == "Y" ]] || return 0
compose_cmd "$NEXUS_ROOT" stop
info "已停止"
}
ops_start_stack() {
compose_cmd "$NEXUS_ROOT" up -d --remove-orphans
verify_nexus_1panel_network "$NEXUS_ROOT" || return 1
verify_health "$NEXUS_ROOT" "启动" || true
}
ops_logs() {
local svc="${1:-nexus}"
echo ""
read -r -p "跟踪日志行数 [80]: " n
n="${n:-80}"
compose_cmd "$NEXUS_ROOT" logs --tail="$n" -f "$svc"
}
ops_status() {
if [[ "$NX_RUNTIME" == "docker" ]]; then
compose_cmd "$NEXUS_ROOT" ps
elif [[ "$NX_RUNTIME" == "supervisor" ]]; then
supervisorctl status nexus
fi
echo ""
local port h code
port="$(nexus_publish_port "$NEXUS_ROOT")"
h=$(curl -sf "http://127.0.0.1:${port}/health" 2>/dev/null || echo "fail")
info "/health → ${h}"
local cname
cname="$(nexus_container_name 2>/dev/null || true)"
code=$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:${port}/app/install.html" 2>/dev/null || echo "000")
if [[ -n "$cname" ]] && nexus_container_has_install_lock "$cname"; then
if [[ "$code" == "404" ]]; then
info "/app/install.html → 已归档 (HTTP 404)"
else
warn "/app/install.html → 应已归档但 HTTP ${code}"
fi
else
info "/app/install.html → HTTP ${code}"
fi
}
ops_backup_now() {
NO_BACKUP=false
backup_mysql "$NEXUS_ROOT"
}
ops_install_cron() {
bash "${NX_DIR}/install_ops_cron.sh"
}
ops_update() {
local args=()
PRUNE_IMAGES=false
NO_BACKUP=false
NO_CACHE=false
read -r -p "跳过 MySQL 备份? [y/N]: " nb
[[ "$nb" == "y" || "$nb" == "Y" ]] && args+=(--no-backup)
read -r -p "无缓存重建镜像? [y/N]: " nc
[[ "$nc" == "y" || "$nc" == "Y" ]] && args+=(--no-cache)
read -r -p "升级后清理悬空镜像? [y/N]: " pr
[[ "$pr" == "y" || "$pr" == "Y" ]] && args+=(--prune)
bash "${NX_DIR}/update.sh" "${args[@]}"
pause_enter
}
require_installed() {
if ! is_stack_installed; then
warn "尚未安装,请先使用菜单 [1] 安装"
pause_enter
return 1
fi
require_root
load_secrets
load_saved_profile "$NEXUS_ROOT"
detect_runtime
return 0
}
menu_main() {
load_secrets
while true; do
menu_header "运维菜单"
cat <<'EOF'
── 安装 ──
[1] 安装向导(新机 / 迁机 / 档位)
[2] 全新安装 → /app/install.html
── 日常运维(需已安装)──
[3] 状态 + 健康检查
[4] 一键更新(pull + 重建镜像)★
[5] 重启 NexusPython
[6] 查看 Nexus 日志
[7] 启动 / 停止 Compose 栈
[8] 重建镜像并启动(--build nexus
[9] 备份 MySQL
[e] 安装巡检/备份 cronhealth_monitor + db_backup
[v] 1Panel 安装/运维验收脚本
── 其它 ──
[a] 检查 Git 是否有更新
[b] 端口 / 防火墙检查
[c] 进入 Nexus 容器 shell
[d] 1Panel 反代说明
[0] 退出
EOF
read -r -p "请选择: " choice
case "$choice" in
1) menu_install ;;
2)
require_root
if is_stack_installed; then
warn "将执行全新安装(清除 nexus-state 卷内旧配置并重建容器)"
read -r -p "确认继续? [y/N]: " fresh_ok
[[ "$fresh_ok" == "y" || "$fresh_ok" == "Y" ]] || continue
fi
exec bash "${NX_DIR}/install-nexus-fresh.sh" --profile "${NEXUS_PROFILE:-2c8g}"
;;
3)
require_root
if is_stack_installed; then
load_saved_profile "$NEXUS_ROOT"
detect_runtime
ops_status
else
check_ports_preflight "$NEXUS_ROOT"
fi
pause_enter
;;
4)
require_installed || continue
ops_update
;;
5)
require_installed || continue
ops_restart_nexus
pause_enter
;;
6)
require_installed || continue
ops_logs nexus
;;
7)
require_installed || continue
echo " [1] 启动 [2] 停止 [3] 重启栈"
read -r -p "选: " s
case "$s" in
1) ops_start_stack ;;
2) ops_stop_stack ;;
3) ops_restart_stack ;;
*) warn "无效" ;;
esac
pause_enter
;;
8)
require_installed || continue
read -r -p "无缓存重建? [y/N]: " nc
if [[ "$nc" == "y" || "$nc" == "Y" ]]; then
compose_cmd "$NEXUS_ROOT" build --no-cache nexus
fi
compose_cmd "$NEXUS_ROOT" up -d --build --remove-orphans nexus
verify_nexus_1panel_network "$NEXUS_ROOT" || true
verify_health "$NEXUS_ROOT" "重建" || true
pause_enter
;;
9)
require_installed || continue
ops_backup_now
pause_enter
;;
e|E)
require_root
ops_install_cron
pause_enter
;;
v|V)
require_root
bash "${NX_DIR}/verify-1panel-install-wizard.sh"
pause_enter
;;
a|A)
require_root
cmd_check
pause_enter
;;
b|B)
require_root
check_ports_preflight "$NEXUS_ROOT"
is_stack_installed && check_ports_post "$NEXUS_ROOT" || true
pause_enter
;;
c|C)
require_installed || continue
compose_cmd "$NEXUS_ROOT" exec nexus bash || compose_cmd "$NEXUS_ROOT" exec nexus sh
;;
d|D)
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) exit 0 ;;
*) warn "无效选项"; sleep 1 ;;
esac
done
}
nx_main() {
local sub="${1:-}"
install_nx_cli
load_secrets
case "$sub" in
""|menu|god|ops|admin)
# god/ops 已合并进主菜单,保留别名兼容
[[ "$sub" == "god" || "$sub" == "ops" || "$sub" == "admin" ]] && \
warn "「上帝菜单」已合并进 nx 主菜单,直接选对应项即可"
menu_main
;;
install) menu_install ;;
update|upgrade)
require_root
shift || true
exec bash "${NX_DIR}/update.sh" "$@"
;;
install-fresh|fresh)
require_root
exec bash "${NX_DIR}/install-nexus-fresh.sh" "$@"
;;
install-auto|auto)
require_root
if is_stack_installed; then
warn "已安装,install-auto 将执行升级而非重复安装"
exec bash "${NX_DIR}/update.sh"
else
run_install "${NEXUS_PROFILE:-2c8g}" ""
fi
;;
health)
require_root
is_stack_installed && ops_status || check_ports_preflight "$NEXUS_ROOT"
;;
cron)
require_root
ops_install_cron
;;
verify)
require_root
bash "${NX_DIR}/verify-1panel-install-wizard.sh"
;;
-h|--help)
cat <<EOF
用法: nx [子命令]
(无) 统一运维菜单(安装 + 升级 + 重启 + 日志)
update 一键更新(等同 bash deploy/update.sh
install-fresh 全新安装(/app/install.html
install-auto 非交互安装(默认 2c8g)
health 健康检查
cron 安装 health_monitor + db_backup crontab
verify 运行 1Panel 验收脚本
god / ops 已合并进主菜单(兼容别名)
curl 入口:
安装 curl -fsSL .../deploy/quick-install.sh | bash
更新 curl -fsSL .../deploy/update.sh | bash
EOF
;;
*)
main "$@"
;;
esac
}
chmod +x "${NX_DIR}/nx" 2>/dev/null || true
nx_main "$@"