BASH脚本中的多线程ping

时间:2017-09-03 12:51:09

标签: multithreading bash

我在这里看了一下,在BASH环境中ping的多线程似乎只有一个问题。

代码

data=$(<~/Desktop/hosts.txt)
    for line in $data
    do
      ping -c1 $line &> /dev/null &
        echo $line is reachable ||
        echo $line is down
     done

问题是它循环遍历文件内的IP地址范围,并报告所有IP地址都是可达的,而事实上只有3个/ 24个可以到达...

我试图通过向ping中添加-W 1来减慢扫描速度,但这会导致性能不合标准,并且需要使用多线程

2 个答案:

答案 0 :(得分:4)

按照编码,你有2个独立的,无关的命令:

# run `ping` and place in background
ping -c1 $line &

# regardless of what the `ping` command does ... always
# print 'reachable` and if that fails print `down`
echo $line is reachable || echo $line is down

我假设您真正想要的是使用ping(成功或失败)的结果来确定要发出的echo命令;在这种情况下,您需要用双“&amp;&amp;”替换单个&像这样:

ping -c1 $line &&
echo $line is reachable ||
echo $line is down

虽然这应该提供条件输出,但现在您的ping在前台一次执行一次。

如果你想在后台运行你的ping(即“多线程”)也执行条件打印,你可以将ping/echo/echo代码放在一个函数中,然后在你的for循环调用函数...确保将函数调用放在后台,例如:

要ping的网站示例列表:

$ cat pinglist
www.yahoo.com
www.google.com
www.peanut_butter.and_jelly
www.bbc.co.uk
www.not_today_your.not

提议的脚本:

$ cat pinger
#!/bin/bash
function pingit () {

    target=${1}

    # send stdout/stderr to /dev/null since all we need is the return code

    ping -c1 ${target} >/dev/null 2>&1 &&
    echo ${target} is reachable ||
    echo ${target} is down
}

data=$(<pinglist)

for line in ${data}
do
    # call our function and place the call in the background

    pingit ${line} &
done

# wait for all outstanding background jobs to complete before continuing

wait

# [optional] let operator know we're done.
echo "Completed."

一些示例运行,请记住输出消息的顺序将根据每个ping命令的完成速度而有所不同:

$ pinger
www.yahoo.com is reachable
www.google.com is reachable
www.peanut_butter.and_jelly is down
www.bbc.co.uk is reachable
www.not_today_your.not is down
Completed.

$ pinger
www.peanut_butter.and_jelly is down
www.not_today_your.not is down
www.google.com is reachable
www.bbc.co.uk is reachable
www.yahoo.com is reachable
Completed.

我们将再次运行测试并对输出进行排序,忽略“已完成”。消息:

$ pinger | egrep -v "Completed" | sort
www.bbc.co.uk is reachable
www.google.com is reachable
www.not_today_your.not is down
www.peanut_butter.and_jelly is down
www.yahoo.com is reachable

!!!请记住,如果您有一长串要ping的主机并且您正在一个小盒子上运行此脚本,那么如果您同时启动数千个同时进行的ping次呼叫,您的系统管理员可能不会太高兴......并且天堂禁止你犯一个编码错误,产生ping命令的无限循环。

这种类型的不当行为可以被编码(例如,限制未完成的ping次呼叫的数量,或sleep每X次ping次呼叫后的几秒钟等等),但我会把编码留作家庭作业; - )

如果您不想使用某个函数(例如,您正在执行快速命令行循环/ ping),您可以将ping/echo/echo括在括号中并在后台运行此构造,尽管您将要决定如何处理与工作相关的消息,例如:

$ data=$(<pinglist)
$ for line in ${data}
do
    (ping -c1 ${line} >/dev/null 2>&1 && echo ${line} is reachable || echo ${line} is down) &
done
[1]     12212
[2]     12213
[3]     12214
[4]     12215
[5]     12217
www.google.com is reachable
www.peanut_butter.and_jelly is down
www.not_today_your.not is down
www.bbc.co.uk is reachable
www.yahoo.com is reachable
[5] +  Done                    for line in ${data};do;    (ping -c1 ${line} >/dev/null 2>&1 && echo ${line} is reachable || echo ${line} is down) & 2>/dev/null;done
[4] -  Done                    for line in ${data};do;    (ping -c1 ${line} >/dev/null 2>&1 && echo ${line} is reachable || echo ${line} is down) & 2>/dev/null;done
[3]    Done                    for line in ${data};do;    (ping -c1 ${line} >/dev/null 2>&1 && echo ${line} is reachable || echo ${line} is down) & 2>/dev/null;done
[2]    Done                    for line in ${data};do;    (ping -c1 ${line} >/dev/null 2>&1 && echo ${line} is reachable || echo ${line} is down) & 2>/dev/null;done
[1]    Done                    for line in ${data};do;    (ping -c1 ${line} >/dev/null 2>&1 && echo ${line} is reachable || echo ${line} is down) & 2>/dev/null;done

用于屏蔽与作业相关的消息的一个选项(kludge?)需要将ping/echo/echo/&包装在一组大括号中并将stderr指向/ dev / null ......

$ data=$(<pinglist)
$ for line in ${data}
do
    {(ping -c1 ${line} >/dev/null 2>&1 && echo ${line} is reachable || echo ${line} is down) & } 2>/dev/null
done
www.peanut_butter.and_jelly is down
www.not_today_your.not is down
www.google.com is reachable
www.yahoo.com is reachable
www.bbc.co.uk is reachable

...虽然这可能会掩盖您可能感兴趣的一些错误消息,ymmv。

答案 1 :(得分:0)

我会让 GNU Parallel 为我做所有并行操作,一次可能是32个:

parallel -j 32 -a hosts.txt 'ping -c1 {} > /dev/null 2>&1 && echo {} is available || echo {} is down'