以下脚本使用 nc 命令扫描指定网段内的 SSH 端口(22),输出所有可以连通的主机 IP。

#!/bin/bash

# 检查依赖
if ! command -v nc &> /dev/null; then
    echo "错误:未找到 nc 命令,请先安装 netcat(如:apt install netcat-openbsd)"
    exit 1
fi

# 显示使用方法
usage() {
    echo "用法: $0 <网段>"
    echo "示例: $0 192.168.1.0/24"
    echo "      $0 192.168.1.   (自动补全 /24)"
    echo "      $0 10.0.0.1-50   (范围格式)"
    exit 1
}

# 解析网段并生成 IP 列表
generate_ips() {
    local input="$1"
    local ips=()

    # 格式1: 192.168.1.0/24
    if [[ "$input" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}$ ]]; then
        local network="${input%/*}"
        local prefix="${input#*/}"
        local base="${network%.*}"
        local start=1 end=254
        # 仅处理常见的 /24,如需其他掩码可自行扩展
        if [[ "$prefix" -eq 24 ]]; then
            for i in $(seq $start $end); do
                ips+=("$base.$i")
            done
        else
            echo "警告:当前脚本仅支持 /24 掩码,将按 /24 扫描" >&2
            for i in $(seq $start $end); do
                ips+=("$base.$i")
            done
        fi

    # 格式2: 192.168.1.   (自动补全 /24)
    elif [[ "$input" =~ ^([0-9]{1,3}\.){3}$ ]]; then
        local base="${input%?}"   # 去掉末尾的点
        for i in $(seq 1 254); do
            ips+=("$base.$i")
        done

    # 格式3: 10.0.0.1-50
    elif [[ "$input" =~ ^([0-9]{1,3}\.){3}([0-9]{1,3})-([0-9]{1,3})$ ]]; then
        local prefix="${input%-*}"
        local start="${input##*-}"
        local base="${prefix%.*}"
        local last_octet="${prefix##*.}"
        if [[ "$last_octet" -le "$start" ]]; then
            for i in $(seq "$last_octet" "$start"); do
                ips+=("$base.$i")
            done
        else
            echo "错误:起始 IP 大于结束 IP" >&2
            exit 1
        fi
    else
        echo "错误:不支持的网段格式" >&2
        usage
    fi

    echo "${ips[@]}"
}

# 并发扫描控制
scan_ip() {
    local ip="$1"
    if nc -z -w 1 "$ip" 22 2>/dev/null; then
        echo "$ip  SSH 端口开放,可以连通"
    fi
}

# 主程序
if [ $# -ne 1 ]; then
    usage
fi

NETWORK="$1"
IP_LIST=($(generate_ips "$NETWORK"))

if [ ${#IP_LIST[@]} -eq 0 ]; then
    echo "没有生成任何 IP,请检查输入"
    exit 1
fi

echo "开始扫描 ${#IP_LIST[@]} 个主机的 22 端口(超时 1 秒)..."
echo "----------------------------------------"

# 并发数限制(可调整)
MAX_JOBS=50
running=0

for ip in "${IP_LIST[@]}"; do
    scan_ip "$ip" &
    ((running++))
    if [ $running -ge $MAX_JOBS ]; then
        wait -n   # 等待任意一个后台任务完成
        ((running--))
    fi
done

wait   # 等待所有剩余任务完成
echo "----------------------------------------"
echo "扫描完成"

使用方法

  1. 保存脚本(如 scan_ssh.sh)并赋予执行权限:

    chmod +x scan_ssh.sh
  2. 运行扫描,支持三种网段格式:

    ./scan_ssh.sh 192.168.1.0/24      # CIDR 格式(实际按 /24 处理)
    ./scan_ssh.sh 192.168.1.          # 点结尾,自动补全 1-254
    ./scan_ssh.sh 10.0.0.1-50         # 范围格式(起始-结束,仅最后一段)
  3. 输出示例

    开始扫描 254 个主机的 22 端口(超时 1 秒)...
    ----------------------------------------
    192.168.1.10  SSH 端口开放,可以连通
    192.168.1.22  SSH 端口开放,可以连通
    ----------------------------------------
    扫描完成

说明

  • 使用 nc -z -w 1 检测端口:-z 仅连接不发送数据,-w 1 设置超时 1 秒。
  • 并发扫描(默认 50 个任务同时进行),可根据网络环境调整 MAX_JOBS 值。
  • nc 不支持 -z(如某些 BSD 版本),可改用 nc -w 1 <ip> 22 < /dev/null,但本脚本按常见 Linux 环境编写。
  • 如需扫描其他端口(如自定义 SSH 端口),将脚本中的 22 替换为相应端口号即可。

简化版本

#!/bin/bash

# 检测 IP 列表文件中的主机是否可 Ping 通,结果同时输出到屏幕和日志文件
# 用法: ./ping_check.sh <ip_list_file> [output_log_file]

# 默认输出文件名(带时间戳)
DEFAULT_LOG_FILE="ping_result_$(date +%Y%m%d_%H%M%S).log"

# 检查参数
if [ $# -lt 1 ]; then
    echo "用法: $0 <ip_list_file> [output_log_file]"
    echo "示例: $0 ip_list.txt                # 自动生成日志文件"
    echo "      $0 ip_list.txt result.log     # 指定日志文件"
    exit 1
fi

IP_FILE="$1"
LOG_FILE="${2:-$DEFAULT_LOG_FILE}"

# 检查 IP 列表文件是否存在
if [ ! -f "$IP_FILE" ]; then
    echo "错误: 文件 '$IP_FILE' 不存在"
    exit 1
fi

# 检查 ping 命令
if ! command -v ping &> /dev/null; then
    echo "错误: 未找到 ping 命令,请先安装。"
    exit 1
fi

# 清空(或创建)日志文件,并写入开始时间
echo "检测开始时间: $(date '+%Y-%m-%d %H:%M:%S')" | tee "$LOG_FILE"
echo "IP 列表文件: $IP_FILE" | tee -a "$LOG_FILE"
echo "----------------------------------------" | tee -a "$LOG_FILE"

TOTAL=0
REACHABLE=0
UNREACHABLE=0

# 逐行读取 IP 地址
while IFS= read -r ip || [ -n "$ip" ]; do
    # 跳过空行和注释行
    [[ -z "$ip" || "$ip" =~ ^# ]] && continue

    TOTAL=$((TOTAL + 1))

    # 发送一个 ping 包,超时 1 秒
    if ping -c 1 -W 1 "$ip" &> /dev/null; then
        echo "可达 : $ip" | tee -a "$LOG_FILE"
        REACHABLE=$((REACHABLE + 1))
    else
        echo "不可达 : $ip" | tee -a "$LOG_FILE"
        UNREACHABLE=$((UNREACHABLE + 1))
    fi
done < "$IP_FILE"

echo "----------------------------------------" | tee -a "$LOG_FILE"
echo "检测完成: 总计 $TOTAL, 可达 $REACHABLE, 不可达 $UNREACHABLE" | tee -a "$LOG_FILE"
echo "日志已保存至: $LOG_FILE"

使用方法
保存脚本为 scan_ssh.sh,执行 chmod +x scan_ssh.sh

运行:./scan_ssh.sh 192.168.1.(注意末尾的点)

文档更新时间: 2026-04-14 09:26   作者:月影鹏鹏
IT运维支持-AIWALY-月影工作室