diff --git a/install.sh b/install.sh index 5a9a0ee..e93f482 100644 --- a/install.sh +++ b/install.sh @@ -648,9 +648,10 @@ install_pm2() { } ################################################################################ -# 端口检测和配置 +# 智能端口检测和配置 ################################################################################ +# 检查端口是否可用(保留用于兼容性) check_port_available() { local port=$1 if command -v netstat &> /dev/null; then @@ -665,22 +666,188 @@ check_port_available() { return 0 # 端口可用 } +# 智能检测端口状态和占用进程 +check_port_status() { + local port=$1 + + # 1. 检查端口是否被监听 + if command -v netstat &> /dev/null; then + if ! netstat -tuln 2>/dev/null | grep -q ":${port} "; then + echo "available" + return 0 + fi + elif command -v ss &> /dev/null; then + if ! ss -tuln 2>/dev/null | grep -q ":${port} "; then + echo "available" + return 0 + fi + else + echo "available" + return 0 + fi + + # 2. 端口被占用,检查是什么进程 + local process="" + + if command -v netstat &> /dev/null; then + process=$(netstat -tulnp 2>/dev/null | grep ":${port} " | awk '{print $7}' | cut -d'/' -f2 | head -1) + fi + + if [[ -z "$process" ]] && command -v ss &> /dev/null; then + process=$(ss -tulnp 2>/dev/null | grep ":${port} " | grep -oP '\".*?\"' | tr -d '"' | cut -d',' -f1 | head -1) + fi + + # 3. 根据进程返回状态 + if [[ -z "$process" ]]; then + # 无法获取进程名(可能权限不足) + echo "occupied" + return 1 + elif [[ "$process" == "nginx" ]] || [[ "$process" =~ ^nginx: ]]; then + # Nginx占用 + echo "nginx" + return 1 + elif [[ "$process" == "apache2" ]] || [[ "$process" == "httpd" ]] || [[ "$process" =~ apache ]]; then + # Apache占用 + echo "apache" + return 2 + else + # 其他进程 + echo "other:$process" + return 3 + fi +} + +# 改进的端口配置函数 configure_ports() { - print_step "端口配置" + print_step "智能端口配置" echo "" - # 检测80端口 - if ! check_port_available 80; then - print_warning "检测到 80 端口已被占用" - echo "" - echo "80端口被其他服务占用,您可以:" - echo -e "${GREEN}[1]${NC} 使用其他HTTP端口 (例如: 8080, 8888)" - echo -e "${GREEN}[2]${NC} 停止占用80端口的服务" - echo "" + # 全局标志:是否共用Nginx端口 + SHARE_NGINX=false - read -p "请选择 [1-2]: " port_choice < /dev/tty + # ========== 检测80端口 ========== + port_80_status=$(check_port_status 80) + + case $port_80_status in + "available") + print_success "80 端口可用" + HTTP_PORT=80 + ;; + + "nginx") + print_info "检测到 Nginx 已占用 80 端口" + echo "" + echo "🎯 好消息:可以通过虚拟主机配置与现有Nginx共用此端口!" + echo "" + echo "请选择部署方式:" + echo "" + echo -e "${GREEN}[1]${NC} 共用80端口(推荐)" + echo " ✅ 需要配置不同的域名" + echo " ✅ 访问: http://your-domain.com" + echo " ✅ 不需要端口号" + echo "" + echo -e "${GREEN}[2]${NC} 使用其他HTTP端口" + echo " ℹ️ 独立端口" + echo " ℹ️ 访问: http://your-domain.com:8080" + echo "" + + while true; do + read -p "请选择 [1-2]: " choice < /dev/tty + + if [[ "$choice" == "1" ]]; then + HTTP_PORT=80 + SHARE_NGINX=true + print_success "将与现有Nginx共用80端口(虚拟主机模式)" + print_info "提示: 请确保使用不同的域名区分站点" + break + elif [[ "$choice" == "2" ]]; then + # 选择其他端口的逻辑 + while true; do + read -p "请输入HTTP端口 [建议: 8080]: " custom_port < /dev/tty + custom_port=${custom_port:-8080} + + if [[ ! "$custom_port" =~ ^[0-9]+$ ]] || [[ $custom_port -lt 1024 ]] || [[ $custom_port -gt 65535 ]]; then + print_error "端口范围: 1024-65535" + continue + fi + + if ! check_port_available $custom_port; then + print_error "端口 $custom_port 已被占用,请选择其他端口" + continue + fi + + HTTP_PORT=$custom_port + print_success "将使用 HTTP 端口: $HTTP_PORT" + break + done + break + else + print_error "无效选项,请重新选择" + fi + done + ;; + + "apache") + print_warning "检测到 Apache 已占用 80 端口" + echo "" + echo "⚠️ Apache和Nginx不能同时监听同一端口" + echo "" + echo "请选择解决方案:" + echo "" + echo -e "${GREEN}[1]${NC} 停止Apache,改用Nginx" + echo " ⚠️ 需要迁移Apache配置" + echo "" + echo -e "${GREEN}[2]${NC} 使用其他HTTP端口(推荐)" + echo " ✅ 不影响现有Apache服务" + echo "" + + while true; do + read -p "请选择 [1-2]: " choice < /dev/tty + + if [[ "$choice" == "1" ]]; then + print_info "正在停止Apache..." + systemctl stop apache2 2>/dev/null || systemctl stop httpd 2>/dev/null || true + systemctl disable apache2 2>/dev/null || systemctl disable httpd 2>/dev/null || true + HTTP_PORT=80 + print_success "Apache已停止,将使用80端口" + break + elif [[ "$choice" == "2" ]]; then + # 选择其他端口 + while true; do + read -p "请输入HTTP端口 [建议: 8080]: " custom_port < /dev/tty + custom_port=${custom_port:-8080} + + if [[ ! "$custom_port" =~ ^[0-9]+$ ]] || [[ $custom_port -lt 1024 ]] || [[ $custom_port -gt 65535 ]]; then + print_error "端口范围: 1024-65535" + continue + fi + + if ! check_port_available $custom_port; then + print_error "端口 $custom_port 已被占用,请选择其他端口" + continue + fi + + HTTP_PORT=$custom_port + print_success "将使用 HTTP 端口: $HTTP_PORT" + break + done + break + else + print_error "无效选项,请重新选择" + fi + done + ;; + + "occupied"|other:*) + process=${port_80_status#other:} + if [[ "$port_80_status" == "occupied" ]]; then + print_warning "80 端口已被占用(无法识别进程)" + else + print_warning "80 端口被进程 ${process} 占用" + fi + echo "" + echo "请选择其他HTTP端口" - if [[ "$port_choice" == "1" ]]; then while true; do read -p "请输入HTTP端口 [建议: 8080]: " custom_port < /dev/tty custom_port=${custom_port:-8080} @@ -699,47 +866,113 @@ configure_ports() { print_success "将使用 HTTP 端口: $HTTP_PORT" break done - else - print_info "请手动停止占用80端口的服务后重新运行此脚本" - echo "" - print_info "查看端口占用: netstat -tunlp | grep :80" - print_info "或者: ss -tunlp | grep :80" - exit 1 - fi - else - print_success "80 端口可用" - fi + ;; + esac - # 检测443端口(仅在使用HTTPS时需要) + echo "" + + # ========== 检测443端口(仅在使用HTTPS时需要)========== if [[ "$USE_DOMAIN" == "true" ]] && [[ "$SSL_METHOD" != "8" ]]; then - if ! check_port_available 443; then - print_warning "检测到 443 端口已被占用" - echo "" + port_443_status=$(check_port_status 443) - while true; do - read -p "请输入HTTPS端口 [建议: 8443]: " custom_https_port < /dev/tty - custom_https_port=${custom_https_port:-8443} + case $port_443_status in + "available") + print_success "443 端口可用" + HTTPS_PORT=443 + ;; - if [[ ! "$custom_https_port" =~ ^[0-9]+$ ]] || [[ $custom_https_port -lt 1024 ]] || [[ $custom_https_port -gt 65535 ]]; then - print_error "端口范围: 1024-65535" - continue + "nginx") + print_info "检测到 Nginx 已占用 443 端口" + echo "" + + if [[ "$SHARE_NGINX" == "true" ]]; then + # 如果HTTP端口也是共用的,默认继续共用 + echo "🎯 将继续与现有Nginx共用443端口(虚拟主机模式)" + HTTPS_PORT=443 + print_success "将与现有Nginx共用443端口" + else + echo "请选择部署方式:" + echo "" + echo -e "${GREEN}[1]${NC} 共用443端口" + echo " ✅ 需要配置不同的域名" + echo "" + echo -e "${GREEN}[2]${NC} 使用其他HTTPS端口" + echo " ℹ️ 独立端口(如8443)" + echo "" + + while true; do + read -p "请选择 [1-2]: " choice < /dev/tty + + if [[ "$choice" == "1" ]]; then + HTTPS_PORT=443 + SHARE_NGINX=true + print_success "将与现有Nginx共用443端口" + break + elif [[ "$choice" == "2" ]]; then + # 选择其他端口 + while true; do + read -p "请输入HTTPS端口 [建议: 8443]: " custom_https_port < /dev/tty + custom_https_port=${custom_https_port:-8443} + + if [[ ! "$custom_https_port" =~ ^[0-9]+$ ]] || [[ $custom_https_port -lt 1024 ]] || [[ $custom_https_port -gt 65535 ]]; then + print_error "端口范围: 1024-65535" + continue + fi + + if ! check_port_available $custom_https_port; then + print_error "端口 $custom_https_port 已被占用,请选择其他端口" + continue + fi + + HTTPS_PORT=$custom_https_port + print_success "将使用 HTTPS 端口: $HTTPS_PORT" + break + done + break + else + print_error "无效选项,请重新选择" + fi + done fi + ;; - if ! check_port_available $custom_https_port; then - print_error "端口 $custom_https_port 已被占用,请选择其他端口" - continue + "apache"|"occupied"|other:*) + # Apache或其他进程占用443,需要换端口 + if [[ "$port_443_status" == "apache" ]]; then + print_warning "检测到 Apache 已占用 443 端口" + elif [[ "$port_443_status" == "occupied" ]]; then + print_warning "443 端口已被占用" + else + process=${port_443_status#other:} + print_warning "443 端口被进程 ${process} 占用" fi + echo "" - HTTPS_PORT=$custom_https_port - print_success "将使用 HTTPS 端口: $HTTPS_PORT" - break - done - else - print_success "443 端口可用" - fi + while true; do + read -p "请输入HTTPS端口 [建议: 8443]: " custom_https_port < /dev/tty + custom_https_port=${custom_https_port:-8443} + + if [[ ! "$custom_https_port" =~ ^[0-9]+$ ]] || [[ $custom_https_port -lt 1024 ]] || [[ $custom_https_port -gt 65535 ]]; then + print_error "端口范围: 1024-65535" + continue + fi + + if ! check_port_available $custom_https_port; then + print_error "端口 $custom_https_port 已被占用,请选择其他端口" + continue + fi + + HTTPS_PORT=$custom_https_port + print_success "将使用 HTTPS 端口: $HTTPS_PORT" + break + done + ;; + esac + + echo "" fi - # 检测后端端口 + # ========== 检测后端端口 ========== if ! check_port_available 40001; then print_warning "检测到 40001 端口已被占用" echo "" @@ -773,6 +1006,9 @@ configure_ports() { echo " - HTTPS端口: $HTTPS_PORT" fi echo " - 后端端口: $BACKEND_PORT" + if [[ "$SHARE_NGINX" == "true" ]]; then + echo " - 模式: 虚拟主机共用端口 ✅" + fi echo "" }