運維指令碼:網路連通性測試

小书童·阿杰發表於2024-11-29

1. 背景介紹

在日常運維工作中,網路連通性是確保系統穩定性和高可用性的關鍵因素之一。透過測試網路連通性,運維人員可以快速診斷網路問題,判斷系統與其他裝置或服務的連線狀態。這對於預防和處理網路故障至關重要。

本文將介紹如何編寫和使用一個簡單的運維指令碼,來自動化測試伺服器的網路連通性。

2. 目標描述

本文的目標是建立一個運維指令碼,用於測試伺服器之間的網路連線是否正常。該指令碼能夠:

  • 檢查與目標IP或域名的連通性。
  • 提供網路連通性測試的結果(如是否連線成功,響應時間等)。
  • 對不同的網路故障型別進行簡單的錯誤提示,幫助快速定位問題。

3. 指令碼設計思路

在測試網路連通性時,我們通常會使用以下工具:

  • Nc 命令:用來測試網路連線性,檢查目標主機是否可達。
  • Traceroute 命令(可選):用於分析網路路由,幫助定位中斷的節點。

指令碼設計應簡潔明瞭,能夠透過引數傳遞目標IP或域名,並且輸出直觀的測試結果。

4. 指令碼示例

#!/bin/bash
# checkConnectStatus.sh
# 批次測試網路連通性指令碼

log_err() {
    printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[31mERROR: \033[0m$@\n"
}

log_info() {
    printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[32mINFO: \033[0m$@\n"
}

log_warning() {
    printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[33mWARNING: \033[0m$@\n"
}

THREADS=5
# 等待佇列初始化
queue_init() {
    tmp="/tmp/$$.fifo"
    mkfifo $tmp
    exec 6<>$tmp
    rm -f $tmp
 
    for ((i = 1; i <= $THREADS; i++)); do
        echo
    done >&6
}

init() {    
    connectConfigDirPath="conf"
    if [ ! -d "$connectConfigDirPath" ];then
        mkdir $connectConfigDirPath
    fi
    connectFileName="${connectConfigDirPath}/connect.csv"
    if [ ! -f "$connectFileName" ];then
        echo "測試地址|測試結果|狀態" > $connectFileName
    fi

    # 檢查是否存在nc命令
    if [ -n "$(rpm -qa | grep 'ncat')" ];then
        yum -y install nc > /dev/null 2>&1
        if [ $? -ne 0 ];then
            log_err "[init] yum install nc failed! 請手動安裝nc命令"
        fi
    fi

    # 引數為空,列印使用方式
    if [ $# -eq 0 ]; then
        usage
    fi
    while [[ $# -gt 0 ]]; do
        case $1 in
        --fileName)
            connectIpPortFileName=$2
            shift
            shift
            ;;  
        * | --help)
            usage
            ;;
        esac
    done
    
}

usage() {
    echo "Usage: $0 
        --fileName  填寫測試連通性檔案
        "
    exit 1
}


checkConnectToFile() {
    local url=$1
    local ip=$(echo $url | awk -F":" '{print $1}')
    local port=$(echo $url | awk -F":" '{print $2}')
    local data=$(nc -zv -w 5 $ip $port 2>&1 | tr "\n" " ")
    local message="網路連通性正常"
    if [ -n "$(echo $data | grep 'Ncat: 0 bytes sent, 0 bytes received')" ];then
        log_info "[connect] url: $url data:[$data] msg: $message"
    else
        local message="網路連通性異常"
        log_err "[connect] url: $url data:[$data] msg: $message"
    fi
        # 將測試結果記錄到檔案中,因使用多執行緒檔案操作加鎖 
    {
        # 檔案執行過程加鎖,等待直到可以鎖定檔案
        flock 002   
        # 結果記錄到檔案中
        echo "$url|$data|$message" >> $connectFileName
    } 002>"${connectFileName}.lock" # 002是檔案描述符,此處用於解鎖
}


readFileToConnect() {
    while read -r line;do
        local IPList=$(echo $line | awk -F"|" '{print $1}')
        local PortList=$(echo $line | awk -F"|" '{print $2}')
        local conncetHostPortArray=()
        # 配置資料處理
        {
            # 多IP情況下
            if [ -n "$(echo $IPList | grep ',')" ];then
                # 進行遍歷
                IFS=',' read -r -a ipArray <<< "$IPList"
                for ip in ${ipArray[@]};do
                    local strLength=$(echo -n "$ip" | wc -c)
                    # 小於3則進行拼接
                    if [ $strLength -le 3 ];then
                        newIP=${startIP:0:-$strLength}$ip
                    else
                        startIP=$ip
                        # 最終IP地址
                        newIP=$ip
                    fi
                    if [ -n "$(echo $PortList | grep ',')" ];then

                        IFS=',' read -r -a portArray <<< "$PortList"
                        for port in ${portArray[@]};do
                            conncetHostPortArray+=("$newIP:$port")
                        done
                    else
                        conncetHostPortArray+=("$newIP:$PortList")
                    fi
                done
            #單IP
            else
                newIP=$IPList
                if [ -n "$(echo $PortList | grep ',')" ];then
                    IFS=',' read -r -a portArray <<< "$PortList"
                    for port in ${portArray[@]};do
                        conncetHostPortArray+=("$newIP:$port")
                    done
                else
                    conncetHostPortArray+=("$newIP:$PortList")
                fi            
            fi
        }

        for hostPort in ${conncetHostPortArray[@]};do
            read -u6
            {
                checkConnectToFile $hostPort               
                echo >&6
            } &
        done
        wait

    done < $connectIpPortFileName
    log_info "最終驗證檔案: $connectFileName"
    remove_file
    exec 6>&-
    exit 0
}

remove_file() {
    rm -f ${connectFileName}.lock
    rm -f $ncErrFileName
}

main() {
    init $@
    queue_init
    readFileToConnect

}

main $@

5. 指令碼所需配置示例

#IP與埠使用 | 進行分割,多IP或多埠使用,分割
192.168.1.38,39,40|443,80,111,1111
192.168.1.10|80,443,80
192.168.1.11,192.68.1.21|80

6. 執行方法

  • 儲存指令碼命為 check_connect_status.sh
  • 執行命令
bash check_connect_status.sh

相關文章