带过滤器的Ping脚本

时间:2018-09-19 17:53:49

标签: bash perl

我有一个文本文件,其中包含主机名和IP地址(每行一个IP和一个主机名)。 IP地址和主机名可以用空格和/或管道分隔,主机名可以在IP地址之前或之后

10.10.10.10 HW-DL11_C023
11.11.11.11 HW-DL11_C024
10.10.10.13 | HW-DL12_C023
11.11.11.12 | HW-DL12_C024
HW-DL13_C023 11.10.10.10 
HW-DL13_C024 21.11.11.11 
HW-DL14_C023 | 11.10.10.10 
HW-DL14_C024 | 21.11.11.11 

下面的脚本应该能够对具有公共分母的主机执行ping操作,例如DL13(有两个设备,它将仅对这两个设备执行ping操作)。我做错了,因为我根本无法使它正常工作?

脚本与数据位于同一目录中;我没有收到错误,所有内容都已格式化。服务器是Linux。

pingme () {
hostfile="/home/rex/u128789/hostfile.txt"
IFS= mapfile -t  hosts < <(cat $hostfile)
for host in "${hosts[@]}"; do
    match=$(echo "$host" | grep -o "\-$1_" | sed 's/-//' | sed 's/_//')
    if [[ "$match" = "$1" ]]; then
        hostname=$(echo "$host" | awk '{print $2}')
        ping -c1 -W1 $(echo "$host" | awk '{print $1}') > /dev/null
        if [[ $? = 0 ]]; then
            echo "$hostname is alive"
        elif [[ $? = 1 ]]; then
            echo "$hostname is dead"
        fi
    fi
done
}

3 个答案:

答案 0 :(得分:1)

尝试将这两行添加到您的代码中:

pingme () {
hostfile="/home/rex/u128789/hostfile.txt"
IFS= mapfile -t  hosts < <(cat $hostfile)
for host in "${hosts[@]}"; do
    echo "Hostname: $host"                      # <-------- ADD THIS LINE -------
    match=$(echo "$host" | grep -o "\-$1_" | sed 's/-//' | sed 's/_//')
    echo "...matched with $match"               # <-------- ADD THIS LINE -------
    if [[ "$match" = "$1" ]]; then
        hostname=$(echo "$host" | awk '{print $2}')
        ping -c1 -W1 $(echo "$host" | awk '{print $1}') > /dev/null
        if [[ $? = 0 ]]; then
            echo "$hostname is alive"
        elif [[ $? = 1 ]]; then
            echo "$hostname is dead"
        fi
    fi
done
}

然后,在运行它时,至少应看到主机列表。

  • 如果不这样做,则说明您没有成功读取文件。
  • 如果这样做,则您的按主机逻辑会出现问题。

恭喜!您已将问题分为两个较小的问题。一旦知道哪一半有问题,就将问题一分为二,直到最小的问题直视您。此时您可能会知道解决方案。如果没有,请将您的发现添加到问题中,我们将在那里提供帮助。

答案 1 :(得分:1)

REX,您需要更详细地说明您要从此示例中获取的IP。您也没有对IMO进行足够的ping操作,并且您的脚本区分字符串(不区分大写)区分大小写。无论如何

首先,检查您的输入和输出是否正常工作,在此示例中,我只是在阅读和打印,如果这样做不起作用,则需要修复权限等:

file="/tmp/hostfile.txt"
while IFS= read -r line ;do
        echo $line
done < "${file}"

接下来,在本示例中,我手动将“ match”设置为DL13,而不是首先尝试使其用作脚本,然后读取$ match上的每一行(如前)和(1)match,如果发现我删除了“ |”,然后将行读入2的数组。如果第一个数组项是IP(包含句点),则将其设置为IP,另一个设置为主机名,否则设置相反。然后运行ping测试。

# BASH4+ Example:
file="/tmp/hostfile.txt"
match="dl13"
while IFS= read -r line ;do

        # -- check for matching string (e.g. dl13 --
        [[ "${line,,}" =~ "${match,,}" ]] || continue

        # -- We found a match, split out host/ip into vars --
        line=$(echo ${line//|})
        IFS=' ' read -r -a items <<< "$line"
        if [[ "${items[0]}" =~ '.' ]] ;then
            host="${items[1]}" ; ip="${items[0]}"
        else
            host="${items[0]}" ; ip="${items[1]}"
        fi

        # -- Ping test --
        ping -q -c3 "${ip}" > /dev/null
        if [ $? -eq 0 ] ;then
            echo "$host is alive!"
        else
            echo "$host is toast!"
        fi

done < "${file}"

答案 2 :(得分:0)

原始代码无法处理输入文件中的管道分隔符或可能颠倒的主机名和IP地址。还会不必要地使用外部程序(grepsed,...)。

尝试一下:

# Enable extended glob patterns - e.g. +(pattern-list)
shopt -s extglob

function pingme
{
    local -r host_denom=$1

    local -r hostfile=$HOME/u128789/hostfile.txt

    local ipaddr host tmp
    # (Add '|' to the usual characters in IFS)
    while IFS=$'| \t\n' read -r ipaddr host ; do
        # Swap host and IP address if necessary
        if [[ $host == +([0-9]).+([0-9]).+([0-9]).+([0-9]) ]] ; then
            tmp=$host
            host=$ipaddr
            ipaddr=$tmp
        fi

        # Ping the host if its name contains the "denominator"
        if [[ $host == *-"$host_denom"_* ]] ; then
            if ping -c1 -W1 -- "$ipaddr" >/dev/null ; then
                printf '%s is alive\n' "$host"
            else
                printf '%s is dead\n' "$host"
            fi
        fi
    done < "$hostfile"

    return 0
}

pingme DL13

最后一行(称为pingme函数)只是一个示例,但使代码执行某些操作至关重要。