我在这里看了一下,在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
来减慢扫描速度,但这会导致性能不合标准,并且需要使用多线程
答案 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'