在 bash 脚本中使用 ping 检查主机可用性

Posted

技术标签:

【中文标题】在 bash 脚本中使用 ping 检查主机可用性【英文标题】:Checking host availability by using ping in bash scripts 【发布时间】:2013-08-09 23:59:44 【问题描述】:

我想写一个脚本,它会不断检查网络中的任何设备,应该整天在线,是否真的在线。我尝试使用 ping,但是

if [ "`ping -c 1 some_ip_here`" ]
then
  echo 1
else
  echo 0
fi

无论我输入有效还是无效的 IP 地址,都会给出1。如何检查特定地址(或更好的 IP 地址列表中的任何设备)是否离线?

【问题讨论】:

你应该考虑使用nmap,它允许你指定IP地址范围。 FWIW,你的 sn-p 对我来说很好用。 不是问题的答案,但您最好使用“$(ping -c 1 some_ip_here)”而不是“ping -c 1 some_ip_here”。 refer this link for more info 【参考方案1】:

Ping 根据错误类型返回不同的退出代码。

ping 256.256.256.256 ; echo $?
# 68

ping -c 1 127.0.0.1 ; echo $?
# 0

ping -c 1 192.168.1.5 ; echo $?
# 2

0 表示主机可达

2 表示不可达

【讨论】:

酷...我还是脚本新手,我认为我的代码中的if 确实检查了退出代码... 确实如此,您的 if 将在任何非 0 退出代码(所有错误)上触发 echo 1 块。但是要弄清楚是哪种错误,您需要检查确切的退出代码。 第一个得到68 吗?我得到2 并且不知道主机。我在第三个示例中得到1,目标主机无法访问。 我在 MacOS 上看到返回码 68,但在 Linux 上它是 2,因为无法解析主机名。 MacOS 上还有一个 -o 选项(我假设在 BSD 中也是如此),它在一个成功的数据包后返回。【参考方案2】:

if 语句中不需要反引号。您可以使用此检查

if ping -c 1 some_ip_here &> /dev/null
then
  echo 1
else
  echo 0
fi

if 命令检查以下命令(ping)的退出代码。如果退出代码为零(这意味着命令成功退出),则将执行 then 块。如果它返回非零退出代码,则将执行 else 块。

【讨论】:

我建议将“&>”替换为“>”,否则脚本会继续运行。 @TNT 这取决于外壳。在 bash 中&> file 等价于> file 2>&1,即重定向标准输出和标准错误。【参考方案3】:

我能想到一个这样的班轮来运行

ping -c 1 127.0.0.1 &> /dev/null && echo success || echo fail

将 127.0.0.1 替换为 IP 或主机名,将 echo 命令替换为任何一种情况下需要执行的操作。

上面的代码会成功,也许可以尝试使用您知道无法访问的 IP 或主机名。

像这样:

ping -c 1 google.com &> /dev/null && echo success || echo fail

还有这个

ping -c 1 lolcatz.ninja &> /dev/null && echo success || echo fail

【讨论】:

非常好的一个班轮!!【参考方案4】:

有 ping 的高级版本 - “fping”,它可以定义以毫秒为单位的超时。

#!/bin/bash
IP='192.168.1.1'
fping -c1 -t300 $IP 2>/dev/null 1>/dev/null
if [ "$?" = 0 ]
then
  echo "Host found"
else
  echo "Host not found"
fi

【讨论】:

ping 还有一个 -t 选项,允许您定义超时。 是的。但在几秒钟内。 fping - 以毫秒为单位,如果您有很多主机要 ping,这很重要。 在“unixy”中 ping -t 不是为了超时,而是为了 TTL。超时是通过 -W 指定的。注意:这仍然可以阻塞很长时间,例如。如果 DNS 服务器消失并且必须解析 DNS 名称。考虑到最近的攻击,应该考虑这一点。 像这里的许多其他答案一样,这个答案具有反模式cmd; if [ $? = 0 ]; then ...,它更好、更惯用地编写if cmd; then ...——if 的目的以及其他流控制语句shell 正是运行一个命令并检查它的退出状态。您应该很少需要直接检查$? 我不会说这是一种反模式,它更多的是个人选择的问题。至于我,独立行中的命令更具可读性。【参考方案5】:

这是一个完整的 bash 脚本,它每 5 秒 ping 一次目标并将错误记录到文件中。

享受吧!

#!/bin/bash
        
        FILE=errors.txt
        TARGET=192.168.0.1

          touch $FILE
          while true;
          do
            DATE=$(date '+%d/%m/%Y %H:%M:%S')
            ping -c 1 $TARGET &> /dev/null
            if [[ $? -ne 0 ]]; then
              echo "ERROR "$DATE
              echo $DATE >> $FILE
            else
              echo "OK "$DATE
            fi
              sleep 5
          done

【讨论】:

【参考方案6】:

仅供参考, 我刚刚使用上面的方法做了一些测试,如果我们使用多 ping(10 个请求)

ping -c10 8.8.8.8 &> /dev/null ;回声$?

如果至少有一个 ping 结果可达,multi ping 命令的结果将为“0”, 如果所有 ping 请求都无法访问,则为“1”。

【讨论】:

将输出发送到 /tmp 中的文件,从像 lxpanel 这样的 GUI 中检查它,你的托盘上有一个向上/向下指示器。或者最近我陷入了像每 30 秒 ping 一次这样的循环,然后在 ping 成功时发出铃声并退出。也许在 android 手机上使用 Termux。不过,它不再是单线了。【参考方案7】:
up=`fping -r 1 $1 `
if [ -z "$up" ]; then
    printf "Host $1 not responding to ping   \n"
    else
    printf "Host $1 responding to ping  \n"
fi

【讨论】:

【参考方案8】:
for i in `cat Hostlist`
do  
  ping -c1 -w2 $i | grep "PING" | awk 'print $2,$3'
done

【讨论】:

【参考方案9】:

这似乎在终端仿真器窗口中运行良好。它循环直到有连接然后停止。

#!/bin/bash

# ping in a loop until the net is up

declare -i s=0
declare -i m=0
while ! ping -c1 -w2 8.8.8.8 &> /dev/null ;
do
  echo "down" $m:$s
  sleep 10
  s=s+10
  if test $s -ge 60; then
    s=0
    m=m+1;
  fi
done
echo -e "--------->>  UP! (connect a speaker) <<--------" \\a

最后的 \a 试图在连接时获得一个 bel char。我一直在尝试在 LXDE/lxpanel 中执行此操作,但一切都会停止,直到我再次建立网络连接。开始时有一个时间作为进度指示器,因为如果你看一个窗口,每行都只是“向下”,你甚至无法判断它正在移动。

【讨论】:

【参考方案10】:

我喜欢检查如下列表的想法:

for i in `cat Hostlist`
do  
  ping -c1 -w2 $i | grep "PING" | awk 'print $2,$3'
done

但是 sn-p 并不关心主机是否无法访问,因此恕我直言,这不是一个很好的答案。

我跑过去写了

for i in `cat Hostlist`
do
  ping -c1 -w2 $i >/dev/null 2>&1 ; echo $i $?
done

然后我可以相应地处理每个。

【讨论】:

欢迎来到 Stack Overflow!为了将来参考,您应该使用反引号字符 (`) 而不是句点字符 (.) 来定义代码围栏。这将修复您的代码块格式。 我不相信我在我的 sn-p 中使用了句号?【参考方案11】:

每隔一秒检查一次主机并在主机到达时发送消息

while :;do ping -c 1 -w 1 -q 8.8.8.8 &>/dev/null && /root/telegram-send.sh "Host reacheble now" && break || sleep 1;done

【讨论】:

以上是关于在 bash 脚本中使用 ping 检查主机可用性的主要内容,如果未能解决你的问题,请参考以下文章

检查主机是否存活的shell脚本

批量检查主机ip之间的连通性脚本

批量检查主机ip之间的连通性脚本

批量检查主机ip之间的连通性脚本

使用ping命令探测主机在线脚本

使用ping命令探测主机在线脚本