支持传入端口参数

This commit is contained in:
jingrow 2025-08-08 02:36:09 +08:00
parent 2be062900e
commit 85e96ca585

View File

@ -175,11 +175,11 @@ log_success() {
} }
log_warning() { log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1" echo -e "${YELLOW}[WARNING]${NC} $1" >&2
} }
log_error() { log_error() {
echo -e "${RED}[ERROR]${NC} $1" echo -e "${RED}[ERROR]${NC} $1" >&2
} }
# 检查是否为root用户 # 检查是否为root用户
@ -280,51 +280,101 @@ get_available_port() {
local base_port="$START_PORT" local base_port="$START_PORT"
local increment="$PORT_INCREMENT" local increment="$PORT_INCREMENT"
# 检查jq是否可用 # 端口分配文件路径
if ! command -v jq &> /dev/null; then local port_file="/home/jingrow/jsite/site_port.json"
log_warning "jq命令不可用使用默认端口 $base_port"
echo "$base_port" # 确保jsite目录存在
return 0 if [ ! -d "/home/jingrow/jsite" ]; then
mkdir -p /home/jingrow/jsite
chown jingrow:jingrow /home/jingrow/jsite
fi fi
# 检查项目是否已有分配的端口 # 检查项目是否已有分配的端口
local port_file="/home/jingrow/jsite/port_assignments.json"
if [ -f "$port_file" ]; then if [ -f "$port_file" ]; then
# 如果项目已存在,返回已分配的端口 # 使用jq查询已分配的端口
local existing_port=$(jq -r ".$site_name // empty" "$port_file" 2>/dev/null || echo "") if command -v jq &> /dev/null; then
if [ -n "$existing_port" ] && [ "$existing_port" != "null" ] && [ "$existing_port" != "empty" ]; then local existing_port=$(jq -r ".$site_name // empty" "$port_file" 2>/dev/null || echo "")
echo "$existing_port" if [ -n "$existing_port" ] && [ "$existing_port" != "null" ] && [ "$existing_port" != "empty" ]; then
return 0 echo "$existing_port"
fi return 0
fi fi
else
# 查找可用端口 # 如果没有jq使用grep和cut来解析JSON
local port="$base_port" local existing_port=$(grep -o "\"$site_name\"[[:space:]]*:[[:space:]]*[0-9]*" "$port_file" 2>/dev/null | cut -d: -f2 | tr -d ' ' || echo "")
local max_attempts=1000 if [ -n "$existing_port" ]; then
local attempts=0 echo "$existing_port"
while [ $attempts -lt $max_attempts ]; do
# 检查端口是否被占用
if ! netstat -tuln 2>/dev/null | grep -q ":$port "; then
# 检查端口是否已被分配
if [ -f "$port_file" ]; then
local used_ports=$(jq -r '.[]' "$port_file" 2>/dev/null || echo "")
if ! echo "$used_ports" | grep -q "^$port$"; then
echo "$port"
return 0
fi
else
echo "$port"
return 0 return 0
fi fi
fi fi
port=$((port + increment)) fi
attempts=$((attempts + 1))
done
log_error "无法找到可用端口,已尝试 $max_attempts" # 如果没有分配的端口,检查是否使用用户指定的起始端口
return 1 local next_port="$base_port"
# 检查用户是否传入了自定义起始端口通过比较START_PORT是否等于默认值3001
local user_specified_port=false
if [ "$base_port" != "3001" ]; then
user_specified_port=true
fi
if [ "$user_specified_port" = true ]; then
# 用户传入了自定义端口,优先使用用户指定的端口
# 检查用户指定的端口是否已被使用
local port_available=true
if [ -f "$port_file" ]; then
if command -v jq &> /dev/null; then
local used_ports=$(jq -r '.[]' "$port_file" 2>/dev/null || echo "")
if echo "$used_ports" | grep -q "^$base_port$"; then
port_available=false
fi
else
local used_ports=$(grep -o ":[[:space:]]*[0-9]*" "$port_file" 2>/dev/null | cut -d: -f2 | tr -d ' ' || echo "")
if echo "$used_ports" | grep -q "^$base_port$"; then
port_available=false
fi
fi
fi
if [ "$port_available" = true ]; then
# 用户指定的端口可用,直接使用
next_port="$base_port"
else
# 用户指定的端口已被使用,使用最大端口号 + 1
if [ -f "$port_file" ]; then
if command -v jq &> /dev/null; then
local max_port=$(jq -r 'max(.[])' "$port_file" 2>/dev/null || echo "$base_port")
if [ -n "$max_port" ] && [ "$max_port" != "null" ]; then
next_port=$((max_port + increment))
fi
else
local max_port=$(grep -o ":[[:space:]]*[0-9]*" "$port_file" 2>/dev/null | cut -d: -f2 | tr -d ' ' | sort -n | tail -1 || echo "$base_port")
if [ -n "$max_port" ]; then
next_port=$((max_port + increment))
fi
fi
fi
fi
else
# 用户没有传入自定义端口,使用自动分配逻辑
if [ -f "$port_file" ]; then
if command -v jq &> /dev/null; then
# 使用jq找到最大端口号
local max_port=$(jq -r 'max(.[])' "$port_file" 2>/dev/null || echo "$base_port")
if [ -n "$max_port" ] && [ "$max_port" != "null" ]; then
next_port=$((max_port + increment))
fi
else
# 使用grep和sort找到最大端口号
local max_port=$(grep -o ":[[:space:]]*[0-9]*" "$port_file" 2>/dev/null | cut -d: -f2 | tr -d ' ' | sort -n | tail -1 || echo "$base_port")
if [ -n "$max_port" ]; then
next_port=$((max_port + increment))
fi
fi
fi
fi
echo "$next_port"
return 0
} }
# 2.7. 保存端口分配 # 2.7. 保存端口分配
@ -332,21 +382,36 @@ save_port_assignment() {
local site_name="$1" local site_name="$1"
local port="$2" local port="$2"
local port_file="/home/jingrow/jsite/port_assignments.json" local port_file="/home/jingrow/jsite/site_port.json"
# 检查jq是否可用 # 确保jsite目录存在
if ! command -v jq &> /dev/null; then if [ ! -d "/home/jingrow/jsite" ]; then
log_warning "jq命令不可用跳过端口分配保存" mkdir -p /home/jingrow/jsite
return 0 chown jingrow:jingrow /home/jingrow/jsite
fi fi
# 创建或更新端口分配文件 # 检查jq是否可用
if [ -f "$port_file" ]; then if command -v jq &> /dev/null; then
# 更新现有文件 # 使用jq保存到JSON文件
jq ". + {\"$site_name\": $port}" "$port_file" > "${port_file}.tmp" && mv "${port_file}.tmp" "$port_file" if [ -f "$port_file" ]; then
# 更新现有文件
jq ". + {\"$site_name\": $port}" "$port_file" > "${port_file}.tmp" && mv "${port_file}.tmp" "$port_file"
else
# 创建新文件
echo "{\"$site_name\": $port}" > "$port_file"
fi
else else
# 创建新文件 # 如果没有jq使用简单的文本处理
echo "{\"$site_name\": $port}" > "$port_file" if [ -f "$port_file" ]; then
# 移除已存在的条目(如果存在)
grep -v "\"$site_name\"" "$port_file" > "${port_file}.tmp" 2>/dev/null || true
mv "${port_file}.tmp" "$port_file"
# 在最后一个大括号前添加新条目
sed -i "s/}$/ \"$site_name\": $port\n}/" "$port_file" 2>/dev/null || echo "{\"$site_name\": $port}" > "$port_file"
else
# 创建新文件
echo "{\"$site_name\": $port}" > "$port_file"
fi
fi fi
# 设置文件权限 # 设置文件权限
@ -356,6 +421,64 @@ save_port_assignment() {
log_success "端口 $port 已分配给项目 $site_name" log_success "端口 $port 已分配给项目 $site_name"
} }
# 2.8. 获取或分配端口(确保一致性)
get_or_assign_port() {
local site_name="$1"
# 获取或分配端口
local port=$(get_available_port "$site_name")
if [ -n "$port" ]; then
# 检查是否已经保存过这个端口分配
local port_file="/home/jingrow/jsite/site_port.json"
local already_saved=false
if [ -f "$port_file" ]; then
if command -v jq &> /dev/null; then
local existing_port=$(jq -r ".$site_name // empty" "$port_file" 2>/dev/null || echo "")
if [ -n "$existing_port" ] && [ "$existing_port" != "null" ] && [ "$existing_port" != "empty" ]; then
already_saved=true
fi
else
local existing_port=$(grep -o "\"$site_name\"[[:space:]]*:[[:space:]]*[0-9]*" "$port_file" 2>/dev/null | cut -d: -f2 | tr -d ' ' || echo "")
if [ -n "$existing_port" ]; then
already_saved=true
fi
fi
fi
# 如果没有保存过,则保存端口分配
if [ "$already_saved" = false ]; then
save_port_assignment "$site_name" "$port"
fi
echo "$port"
return 0
else
log_error "无法为项目 $site_name 分配端口"
return 1
fi
}
# 2.9. 显示端口分配情况
show_port_assignments() {
local port_file="/home/jingrow/jsite/site_port.json"
if [ ! -f "$port_file" ]; then
log_info "暂无端口分配记录"
return 0
fi
log_info "当前端口分配情况:"
if command -v jq &> /dev/null; then
# 使用jq格式化输出
jq -r 'to_entries[] | " - \(.key): \(.value)"' "$port_file" 2>/dev/null || log_warning "无法解析端口分配文件"
else
# 使用grep和sed格式化输出
grep -o '"[^"]*"[[:space:]]*:[[:space:]]*[0-9]*' "$port_file" 2>/dev/null | sed 's/"//g' | sed 's/[[:space:]]*:[[:space:]]*/: /' | sed 's/^/ - /' || log_warning "无法解析端口分配文件"
fi
}
# 3. 克隆jsite项目 # 3. 克隆jsite项目
clone_jsite_project() { clone_jsite_project() {
log_info "开始克隆jsite项目: $SITE_NAME..." log_info "开始克隆jsite项目: $SITE_NAME..."
@ -417,8 +540,7 @@ create_env_file() {
cd /home/jingrow/jsite/$SITE_NAME cd /home/jingrow/jsite/$SITE_NAME
# 获取项目端口 # 获取项目端口
local project_port=$(get_available_port "$SITE_NAME") local project_port=$(get_or_assign_port "$SITE_NAME")
save_port_assignment "$SITE_NAME" "$project_port"
# 更新SITE_URL以使用分配的端口 # 更新SITE_URL以使用分配的端口
local site_url_with_port=$(echo "$SITE_URL" | sed "s|:[0-9]*|:$project_port|") local site_url_with_port=$(echo "$SITE_URL" | sed "s|:[0-9]*|:$project_port|")
@ -463,7 +585,7 @@ create_pm2_config() {
cd /home/jingrow/jsite/$SITE_NAME cd /home/jingrow/jsite/$SITE_NAME
# 获取项目端口 # 获取项目端口
local project_port=$(get_available_port "$SITE_NAME") local project_port=$(get_or_assign_port "$SITE_NAME")
# 创建logs目录 # 创建logs目录
mkdir -p "/home/jingrow/jsite/$SITE_NAME/logs" mkdir -p "/home/jingrow/jsite/$SITE_NAME/logs"
@ -748,7 +870,7 @@ create_traefik_website_config() {
log_info "创建traefik网站配置文件..." log_info "创建traefik网站配置文件..."
# 获取项目端口 # 获取项目端口
local project_port=$(get_available_port "$SITE_NAME") local project_port=$(get_or_assign_port "$SITE_NAME")
# 生成Host规则 # 生成Host规则
local host_rule=$(generate_host_rule "$SITE_URL") local host_rule=$(generate_host_rule "$SITE_URL")
@ -860,7 +982,7 @@ show_deployment_info() {
echo " - 用户: jingrow" echo " - 用户: jingrow"
echo " - jsite目录: /home/jingrow/jsite" echo " - jsite目录: /home/jingrow/jsite"
echo " - 项目目录: /home/jingrow/jsite/$SITE_NAME" echo " - 项目目录: /home/jingrow/jsite/$SITE_NAME"
echo " - 项目端口: $(get_available_port "$SITE_NAME")" echo " - 项目端口: $(get_or_assign_port "$SITE_NAME")"
echo " - Traefik目录: /home/jingrow/traefik-docker" echo " - Traefik目录: /home/jingrow/traefik-docker"
echo " - Traefik管理界面: http://localhost:8080" echo " - Traefik管理界面: http://localhost:8080"
echo " - Traefik网站配置: /home/jingrow/traefik-docker/conf.d/website/$SITE_NAME.yml" echo " - Traefik网站配置: /home/jingrow/traefik-docker/conf.d/website/$SITE_NAME.yml"
@ -886,7 +1008,10 @@ show_deployment_info() {
log_info "Traefik配置信息" log_info "Traefik配置信息"
echo " - 网站配置文件: /home/jingrow/traefik-docker/conf.d/website/$SITE_NAME.yml" echo " - 网站配置文件: /home/jingrow/traefik-docker/conf.d/website/$SITE_NAME.yml"
echo " - 访问域名: $(generate_host_rule "$SITE_URL" | sed 's/Host(`//g' | sed 's/`)//g' | sed 's/ || / 或 /g')" echo " - 访问域名: $(generate_host_rule "$SITE_URL" | sed 's/Host(`//g' | sed 's/`)//g' | sed 's/ || / 或 /g')"
echo " - 后端端口: $(get_available_port "$SITE_NAME")" echo " - 后端端口: $(get_or_assign_port "$SITE_NAME")"
echo ""
# 显示端口分配情况
show_port_assignments
echo "" echo ""
log_info "下一步操作:" log_info "下一步操作:"
echo " 1. 进入项目目录: cd /home/jingrow/jsite/$SITE_NAME" echo " 1. 进入项目目录: cd /home/jingrow/jsite/$SITE_NAME"
@ -895,6 +1020,7 @@ show_deployment_info() {
echo " 4. 访问Traefik管理界面: http://localhost:8080" echo " 4. 访问Traefik管理界面: http://localhost:8080"
echo " 5. 访问项目: $SITE_URL" echo " 5. 访问项目: $SITE_URL"
echo " 6. 检查traefik配置: cat /home/jingrow/traefik-docker/conf.d/website/$SITE_NAME.yml" echo " 6. 检查traefik配置: cat /home/jingrow/traefik-docker/conf.d/website/$SITE_NAME.yml"
echo " 7. 查看端口分配: cat /home/jingrow/jsite/site_port.json"
echo "" echo ""
log_warning "注意请确保防火墙允许80、443、8080端口访问" log_warning "注意请确保防火墙允许80、443、8080端口访问"
} }