BASH脚本中的多线程ping [英] Multithreading ping inside BASH script
问题描述
我到处看看,关于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 sleep
ing 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屋!