#!/bin/bash

# 定义要检测的IP段和端口
ip_ranges=("10.34.44." "10.34.45." "172.168.100." "172.168.200." )
ports=(22 3389 65522)

# 定义输出文件
used_file="used_ips.txt"
unused_file="unused_ips.txt"
merged_used_file="merged_used_ips.txt"
merged_unused_file="merged_unused_ips.txt"

# 清空文件内容
> $used_file
> $unused_file
> $merged_used_file
> $merged_unused_file

# 最大并发数（避免过多进程导致系统性能问题）
MAX_CONCURRENT=50
SEMAPHORE="/tmp/semaphore_$$"

# 创建信号量文件
mkfifo "$SEMAPHORE"
exec 3<> "$SEMAPHORE"
for _ in $(seq $MAX_CONCURRENT); do echo; done >&3

# 检测单个IP
check_ip() {
    local ip=$1

    # 优先检测ICMP（ping）
    if ping -c 1 -W 1 $ip &> /dev/null; then
        # 如果 ping 通，标记为已用
        echo "$ip" >> $used_file
        return
    fi

    # 如果 ping 不通，则检测端口
    for port in "${ports[@]}"; do
        if nc -z -w 1 $ip $port &> /dev/null; then
            # 如果任一端口通，标记为已用
            echo "$ip" >> $used_file
            return
        fi
    done

    # 如果既 ping 不通，端口也不通，标记为未用
    echo "$ip" >> $unused_file
}

# 并发检测所有IP
for range in "${ip_ranges[@]}"; do
    for i in {1..254}; do
        read -u 3 # 从信号量文件中读取，确保并发控制
        {
            ip="${range}${i}"
            check_ip $ip
            echo >&3 # 释放信号量
        } &
    done
done

# 等待所有子进程完成
wait

# 关闭信号量文件
exec 3>&-

# 按顺序对结果文件进行排序
sort -V $used_file -o $used_file
sort -V $unused_file -o $unused_file

# 合并连续IP到范围形式
merge_ips() {
    local input_file=$1
    local output_file=$2
    local prev_ip=""
    local start_ip=""

    while read -r ip; do
        # 提取当前IP的末尾数字
        current_octet=$(echo $ip | awk -F. '{print $4}')

        if [ -z "$prev_ip" ]; then
            # 初始化第一个IP
            start_ip=$ip
            prev_ip=$ip
            continue
        fi

        # 检查当前IP是否与上一个IP连续
        prev_octet=$(echo $prev_ip | awk -F. '{print $4}')
        if [ $((prev_octet + 1)) -ne $current_octet ]; then
            # 如果不连续，将范围写入文件
            if [ "$start_ip" == "$prev_ip" ]; then
                echo "$start_ip" >> $output_file
            else
                echo "$start_ip-$prev_ip" >> $output_file
            fi
            start_ip=$ip
        fi
        prev_ip=$ip
    done < $input_file

    # 写入最后一段范围
    if [ "$start_ip" == "$prev_ip" ]; then
        echo "$start_ip" >> $output_file
    else
        echo "$start_ip-$prev_ip" >> $output_file
    fi
}

# 合并已用和未用IP范围
merge_ips $used_file $merged_used_file
merge_ips $unused_file $merged_unused_file

echo "检测完成！"
echo "已用IP地址存储在 $used_file"
echo "未使用IP地址存储在 $unused_file"
echo "合并后的已用IP范围存储在 $merged_used_file"
echo "合并后的未使用IP范围存储在 $merged_unused_file"

