#!/usr/bin/env bash
set -euo >/dev/null 2>&1
count_undefined_ports() {
local undefined_count=0
for port_name in "${PORTS[@]}"; do
if [ -z "${DEPLOY_VARS[${port_name}]:-}" ]; then
undefined_count=$((undefined_count + 1))
else
local port=${DEPLOY_VARS[${port_name}]}
ALLOCATED_PORTS+=("${port}")
if is_port_occupied "${port}"; then
error "[${port_name}]:${port} is occupied. Please specify an unoccupied port instead."
fi
fi
done
CONFIG["ALLOC_PORT_NUM"]=${undefined_count}
info "Total undefined ports: ${undefined_count} → Need to allocate ${undefined_count} available ports"
}
is_port_occupied() {
local port="$1"
local port_occupied=0
local os_type=${DEPLOY_VARS["OS_TYPE"]}
case "${os_type}" in
macos)
if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1; then
port_occupied=1
fi
;;
linux)
netstat_output=$(netstat -tuln 2>&1)
if echo "${netstat_output}" | grep -q ":$port"; then
port_occupied=1
fi
;;
windows)
if netstat -an | grep -qiE ":$port[^0-9].*LISTENING.*" 2>/dev/null; then
port_occupied=1
fi
;;
esac
if [ "$port_occupied" -eq 1 ]; then
return 0
else
return 1
fi
}
find_available_ports() {
local start_port=${CONFIG["START_PORT"]}
local end_port=${CONFIG["END_PORT"]}
local need_port_num=${CONFIG["ALLOC_PORT_NUM"]}
local allocated_ports=("${ALLOCATED_PORTS[@]:-}")
if [ "$need_port_num" -eq 0 ]; then
return
fi
info "Current allocated port list: ${allocated_ports[*]:-empty}"
info "Scanning port range: $start_port ~ $end_port, need to allocate $need_port_num available ports"
for port in $(seq "$start_port" "$end_port"); do
local is_allocated=0
for allocated_port in "${allocated_ports[@]}"; do
if [ -n "$allocated_port" ]; then
if [ "$port" -eq "$allocated_port" ]; then
is_allocated=1
break
fi
fi
done
if [ "$is_allocated" -eq 1 ]; then
info "Port $port already allocated, skipping"
continue
fi
if is_port_occupied "$port"; then
continue
else
AVAILABLE_PORTS+=("$port")
if [ "${#AVAILABLE_PORTS[@]}" -ge "$need_port_num" ]; then
break
fi
fi
done
if [ "${#AVAILABLE_PORTS[@]}" -lt "$need_port_num" ]; then
error "Only found ${#AVAILABLE_PORTS[@]} available ports, insufficient for $need_port_num (port range: $start_port-$end_port)"
fi
allocated_ports+=("${AVAILABLE_PORTS[@]}")
success "Collected $need_port_num available ports: ${AVAILABLE_PORTS[*]}"
}
assign_ports() {
local port_index=0
info "Starting to assign values to undefined ports..."
for port_name in "${PORTS[@]}"; do
if [ -n "${DEPLOY_VARS[${port_name}]:-}" ]; then
info "[${port_name}] already defined, keeping original value: ${DEPLOY_VARS[${port_name}]}"
else
if [ ${port_index} -lt ${#AVAILABLE_PORTS[@]} ]; then
DEPLOY_VARS["${port_name}"]=${AVAILABLE_PORTS[${port_index}]}
info "[${port_name}] undefined, assigning available port: ${DEPLOY_VARS[${port_name}]}"
port_index=$((port_index + 1))
else
error "[${port_name}] no available ports to assign (available ports: ${#AVAILABLE_PORTS[@]})"
fi
fi
done
success "All port assignments Done!"
}
process_ports() {
count_undefined_ports
find_available_ports
assign_ports
}