feat: 添加智能端口检测和Nginx虚拟主机支持 (v4.0)

新增功能:
- 智能识别占用端口的进程(Nginx/Apache/其他)
- 支持Nginx虚拟主机模式,多网站共用80/443端口
- 根据不同进程提供针对性解决方案
- 优化用户交互体验,提供清晰的选项说明

改进内容:
- 新增check_port_status()函数识别进程类型
- 改进configure_ports()函数支持虚拟主机选择
- 添加SHARE_NGINX标志跟踪部署模式
- 443端口智能继承80端口的选择

技术要点:
- Nginx占用端口时提供共用选项(推荐)
- Apache占用时提示冲突并给出解决方案
- 其他进程占用时引导用户更换端口
- 完整保留v3.0的CORS双重来源支持

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
WanWanYun
2025-11-13 01:07:22 +08:00
parent cfcbc22ae7
commit 20d23509e7

View File

@@ -648,9 +648,10 @@ install_pm2() {
} }
################################################################################ ################################################################################
# 端口检测和配置 # 智能端口检测和配置
################################################################################ ################################################################################
# 检查端口是否可用(保留用于兼容性)
check_port_available() { check_port_available() {
local port=$1 local port=$1
if command -v netstat &> /dev/null; then if command -v netstat &> /dev/null; then
@@ -665,22 +666,102 @@ check_port_available() {
return 0 # 端口可用 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() { configure_ports() {
print_step "端口配置" print_step "智能端口配置"
echo "" echo ""
# 检测80端口 # 全局标志是否共用Nginx端口
if ! check_port_available 80; then SHARE_NGINX=false
print_warning "检测到 80 端口已被占用"
# ========== 检测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 ""
echo "80端口被其他服务占用您可以:" echo "🎯 好消息可以通过虚拟主机配置与现有Nginx共用此端口"
echo -e "${GREEN}[1]${NC} 使用其他HTTP端口 (例如: 8080, 8888)" echo ""
echo -e "${GREEN}[2]${NC} 停止占用80端口的服务" 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 "" echo ""
read -p "请选择 [1-2]: " port_choice < /dev/tty while true; do
read -p "请选择 [1-2]: " choice < /dev/tty
if [[ "$port_choice" == "1" ]]; then if [[ "$choice" == "1" ]]; then
HTTP_PORT=80
SHARE_NGINX=true
print_success "将与现有Nginx共用80端口虚拟主机模式"
print_info "提示: 请确保使用不同的域名区分站点"
break
elif [[ "$choice" == "2" ]]; then
# 选择其他端口的逻辑
while true; do while true; do
read -p "请输入HTTP端口 [建议: 8080]: " custom_port < /dev/tty read -p "请输入HTTP端口 [建议: 8080]: " custom_port < /dev/tty
custom_port=${custom_port:-8080} custom_port=${custom_port:-8080}
@@ -699,21 +780,172 @@ configure_ports() {
print_success "将使用 HTTP 端口: $HTTP_PORT" print_success "将使用 HTTP 端口: $HTTP_PORT"
break break
done done
break
else else
print_info "请手动停止占用80端口的服务后重新运行此脚本" print_error "无效选项,请重新选择"
echo ""
print_info "查看端口占用: netstat -tunlp | grep :80"
print_info "或者: ss -tunlp | grep :80"
exit 1
fi fi
else done
print_success "80 端口可用" ;;
"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 fi
# 检测443端口仅在使用HTTPS时需要 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端口"
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
;;
esac
echo ""
# ========== 检测443端口仅在使用HTTPS时需要==========
if [[ "$USE_DOMAIN" == "true" ]] && [[ "$SSL_METHOD" != "8" ]]; then if [[ "$USE_DOMAIN" == "true" ]] && [[ "$SSL_METHOD" != "8" ]]; then
if ! check_port_available 443; then port_443_status=$(check_port_status 443)
print_warning "检测到 443 端口已被占用"
case $port_443_status in
"available")
print_success "443 端口可用"
HTTPS_PORT=443
;;
"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
;;
"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 "" echo ""
while true; do while true; do
@@ -734,12 +966,13 @@ configure_ports() {
print_success "将使用 HTTPS 端口: $HTTPS_PORT" print_success "将使用 HTTPS 端口: $HTTPS_PORT"
break break
done done
else ;;
print_success "443 端口可用" esac
fi
echo ""
fi fi
# 检测后端端口 # ========== 检测后端端口 ==========
if ! check_port_available 40001; then if ! check_port_available 40001; then
print_warning "检测到 40001 端口已被占用" print_warning "检测到 40001 端口已被占用"
echo "" echo ""
@@ -773,6 +1006,9 @@ configure_ports() {
echo " - HTTPS端口: $HTTPS_PORT" echo " - HTTPS端口: $HTTPS_PORT"
fi fi
echo " - 后端端口: $BACKEND_PORT" echo " - 后端端口: $BACKEND_PORT"
if [[ "$SHARE_NGINX" == "true" ]]; then
echo " - 模式: 虚拟主机共用端口 ✅"
fi
echo "" echo ""
} }