7.4 列出网络上所有的活动主机

当我们涉及大型局域网时,可能需要检查网络上的其他主机是否处于活动状态。一台非活动主机可能有两种情况:要么是没有开机,要么是网络连接有问题。借助shell脚本,我们可以轻易找出并报告网络上的哪一台主机处于活动状态。让我们看看这是如何实现的。

7.4.1 新手上路

在这则攻略中,我们采用两种方法。第一种方法使用ping,第二种方法使用fpingfping并没有默认包含在Linux发行版中。你可以用软件包管理器手动安装。

7.4.2 实战演练

让我们看看可以找出网络上所有活动主机的脚本,以及实现这一目标的其他方法。

  • 方法1

我们可以用ping命令编写脚本来查询一组IP地址同时检查它们是否处于活动状态:

  1. #!/bin/bash
  2. #文件名: ping.sh
  3. # 用途:根据你的网络配置对网络地址192.168.0进行修改.
  4.  
  5. for ip in 192.168.0.{1..255} ;
  6. do
  7. ping $ip -c 2 &> /dev/null ;
  8.  
  9. if [ $? -eq 0 ];
  10. then
  11. echo $ip is alive
  12. fi
  13.  
  14. done

输出如下:

  1. $ ./ping.sh
  2. 192.168.0.1 is alive
  3. 192.168.0.90 is alive
  • 方法2

我们可以用已有的命令行工具来查询网络上的主机状态:

  1. $ fping -a 192.160.1/24 -g 2> /dev/null
  2. 192.168.0.1
  3. 192.168.0.90

或者,使用:

  1. $ fping -a 192.168.0.1 192.168.0.255 -g

7.4.3 工作原理

在方法1中,我们用ping命令找出网络上的活动主机。我们用了一个for循环对一组IP地址进行迭代。这组IP地址依照192.168.0.{1..255}格式生成。像{start..end}这种记法会由shell对其进行扩展并生成一组IP地址,例如,192.168.0.1、192.168.0.2、192.168.0.3等依次类推,直到192.168.0.255。

ping $ip -c 2 &> /dev/null会在每次循环中ping对应的IP地址。-c 2将发送的echo分组数量限制为2。&> /dev/null用于将stderrstdout重定向到 /dev/null,使它们不会在终端上打印出来。我们用 $? 获取退出状态。如果顺利退出,退出状态为0,否则,为非0。因此能够ping通的IP地址就被打印出来。我们也可以打印出不能ping通的IP地址,从而给出一个无法抵达的IP地址列表。

7.4 列出网络上所有的活动主机 - 图1  这里为你准备了一个练习。不是在脚本中使用硬编码形式的IP地址范围,而是修改脚本使其能够从文件或stdin中读取一组IP地址。

在这个脚本中,每一次ping都是依次执行的。即使所有的IP地址都是彼此独立,由于编写的是顺序式程序(sequential program),ping命令也只能按顺序执行。每执行一次ping命令,都要经历一段延迟:发送两个echo分组,并接收回应或等待回应超时。

要是处理255个地址的话,这段延迟的时间可就不短了。我们可以使用并行方式来加速所有ping命令的执行。这个脚本的核心部分是循环体。要使ping命令可以并行执行,可将循环体放入( )&。将命令块放入( ),使其中的命令可作为子shell来执行,而& 可以使之脱离当前线程,在后台继续运行。例如:

  1. (
  2. ping $ip -c2 &> /dev/null ;
  3. if [ $? -eq 0 ];
  4. then
  5. echo $ip is alive
  6. fi
  7. )&
  8.  
  9. wait

for循环体执行多个后台进程,然后结束循环并终止脚本。要想等所有子进程结束之后再终止脚本,我们得使用wait命令。将wait放在脚本最后,它就会一直等到所有的子进程全部结束。

7.4 列出网络上所有的活动主机 - 图2 wait命令使脚本只有在所有的子进程或后台进程全部终止或完成之后才能结束。

请阅读本书所提供的脚本fast_ping.sh。

方法2使用了另一个命令fping。它同时可以ping一组IP地址,而且响应速度非常快。fping的选项如下:

  • 选项 -a指定打印出所有活动主机的IP地址。

  • 选项 -u指定打印出所有无法到达的主机。

  • 选项 -g指定从写作IP/mask的“斜线-子网掩码”记法或者起止IP地址记法中生成IP地址范围。

  1. $ fping -a 192.160.1/24 -g

或者

  1. $ fping -a 192.160.1 192.168.0.255 -g
  • 2>/dev/null将由于主机无法到达所产生的错误信息打印到null设备。

也可以采用命令行参数的方式手动指定一组IP地址,或者从stdin中接收。例如:

  1. $ fping -a 192.168.0.1 192.168.0.5 192.168.0.6
  2. # 将IP地址作为参数传递
  3. $ fping -a <ip.list
  4. # 从文件中传递一组IP地址

7.4.4 补充内容

fping命令可以用来查询网络中的DNS数据。来看看它的具体用法。

fping进行DNS查找

fping有一个选项-d,它通过对每一个echo回应进行DNS查询来返回主机名。使用该选项可以在ping的回应信息中打印出主机名而非IP地址。

  1. $ cat ip.list
  2. 192.168.0.86
  3. 192.168.0.9
  4. 192.168.0.6
  5.  
  6. $ fping -a -d 2>/dev/null <ip.list
  7. www.local
  8. dnss.local

7.4.5 参考

  • 1.5节讲解了数据重定向。

  • 1.15节讲解了数字比较。