63 lines
No EOL
2.1 KiB
Bash
63 lines
No EOL
2.1 KiB
Bash
#!/bin/bash
|
||
|
||
start_port=$1
|
||
needed=$2
|
||
|
||
if [[ -z "$start_port" || -z "$needed" || "$needed" -le 0 ]]; then
|
||
echo "Usage: $0 <start_port> <needed>"
|
||
exit 1
|
||
fi
|
||
|
||
free_ports=()
|
||
found_base=-1
|
||
|
||
check_port() {
|
||
local p=$1
|
||
timeout 1 bash -c "exec 6<>/dev/tcp/127.0.0.1/$p" 2>/dev/null && return 1 || return 0
|
||
}
|
||
for ((port = start_port; port <= start_port + 2000; port++)); do
|
||
if check_port "$port"; then
|
||
# порт свободен
|
||
free_ports+=("$port")
|
||
|
||
# если это первый порт в потенциальном блоке — запомним его
|
||
if [ "${#free_ports[@]}" -eq 1 ]; then
|
||
found_base=$port
|
||
fi
|
||
# если набрали нужное количество подряд свободных
|
||
if [ "${#free_ports[@]}" -eq "$needed" ]; then
|
||
base_port=${free_ports[0]}
|
||
# Считаем, какой порт должен быть в диапазоне 18000–18999
|
||
offset=$((base_port - 19000)) # например, 19015 → offset=15
|
||
mirror_port=$((18000 + offset))
|
||
conflict=false
|
||
# Проверяем весь блок в зеркальном диапазоне 18000+
|
||
for ((i=0; i<needed; i++)); do
|
||
check_mirror=$((18000 + offset + i))
|
||
if ! check_port "$check_mirror"; then
|
||
# порт в 18000+ ЗАНЯТ → конфликт!
|
||
conflict=true
|
||
break
|
||
fi
|
||
done
|
||
if [ "$conflict" = false ]; then
|
||
# Выводим первый порт блока
|
||
echo "$base_port"
|
||
exit 0
|
||
else
|
||
# Конфликт — сбрасываем накопленный блок и продолжаем поиск
|
||
free_ports=()
|
||
found_base=-1
|
||
((port -= needed - 2))
|
||
continue
|
||
fi
|
||
fi
|
||
else
|
||
# порт занят — сбрасываем текущий блок
|
||
free_ports=()
|
||
found_base=-1
|
||
fi
|
||
done
|
||
|
||
echo "NOT_FOUND"
|
||
exit 1 |