Files
Nexus/deploy/nx
T

379 lines
11 KiB
Bash
Raw Normal View History

#!/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
NX_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && 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] 全新库安装向导模式(/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) run_install 2c8g fresh ;;
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 "将停止 MySQL / Redis / Nexus 全部容器"
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
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] 重启全部容器(mysql + redis + nexus
[3] 启动 Compose 栈
[4] 停止 Compose 栈
[5] 重建 Nexus 镜像并启动(up -d --build nexus
── 观测 ──
[6] 状态 + 健康检查
[7] 查看 Nexus 日志(跟踪)
[8] 查看 MySQL / Redis 日志
[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 nexus
verify_health "$NEXUS_ROOT" "重建" || true
pause_enter
;;
6) god_status; pause_enter ;;
7) god_logs nexus ;;
8)
echo "1) mysql 2) redis"
read -r -p "选: " s
[[ "$s" == "1" ]] && god_logs mysql || god_logs redis
;;
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-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-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 "$@"