BASH脚本中的多线程ping [英] Multithreading ping inside BASH script

查看:96
本文介绍了BASH脚本中的多线程ping的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我到处看看,关于BASH环境中ping的多线程问题似乎只有一个.

I've had a look around here and there only seems to be one question raised in regards to the multithreading of ping inside a BASH environment.

代码

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

问题是,它循环访问文件内的IP地址范围,并在实际上只有24个中的3个可访问时将所有IP地址报告为可访问...

The issue is that it cycles through the IP address range inside the file and reports all of the IP addresses as reachable when in fact only 3 out of /24 are reachable...

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

I've attempted to slow the scan down by adding -W 1 to the ping but this results in substandard performance and necessitates the use of multithreading

推荐答案

根据编码,您有2个独立的不相关命令:

As coded you've got 2 separate, unrelated commands:

# 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命令;在这种情况下,您需要用双`&&'替换单个&像这样:

I'm assuming what you really want is to use the results of the ping (success or failure) to determine which echo command to issue; in this case you need to replace the single & with a double `&&' like such:

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

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

While this should provide the conditional output, your pings are now performed one-at-a-time in the foreground.

如果要在后台运行ping(即多线程"),并且还执行条件打印,则可以将ping/echo/echo代码放在函数中,然后将for循环对函数进行调用...确保将函数调用置于后台,例如:

If you want to run your pings in the background (ie, 'multithreaded') and also perform the conditional printing, you could place the ping/echo/echo code inside a function, then in your for loop make a call to the function ... making sure to place the function call in the background, eg:

要ping的站点列表示例:

Sample list of sites to 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命令完成的速度而变化:

Some sample runs, keeping in mind that the order of the output messages will vary based on how quickly each ping command completes:

$ 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.

我们将再次运行测试并对输出进行排序,而忽略已完成".讯息:

We'll run the test again and sort the output, ignoring the 'Completed.' message:

$ 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调用,您的sysadmin可能不会太高兴. .和天堂禁止您犯一个编码错误,该错误会导致ping命令的无限循环.


!!! Keep in mind that if you've got a long list of hosts to ping and you're running this script on a smallish box, your sysadmin might not be too happy if you kick off 10's of thousands of simultaneous ping calls ... and heaven forbid you make a coding mistake that spawns an infinite loop of ping commands.

这种类型的不当行为可以进行编码(例如,限制未完成的ping呼叫的数量,或者在每X次ping呼叫之后的几秒钟内sleep等等),但是我会将该编码留作功课;-)

This type of misbehavior can be coded for (eg, limiting the number of outstanding ping calls, or sleeping for a couple seconds after every X number of ping calls, etc), but I'll leave that coding as homework ;-)

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

If you don't want to bother with a function (eg, you're doing a quick command line loop/ping), you could wrap the ping/echo/echo in parentheses and run this construct in the background, though you'll want to decide how to handle the job-related messages, eg:

$ 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 ...

One option (kludge?) for masking the job related messages requires wrapping our ping/echo/echo/& in a set of braces and directing stderr to /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.

... though this could mask some error messages that you may be interested in, ymmv.

这篇关于BASH脚本中的多线程ping的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆