【问题标题】:Bash loop ping successfulBash 循环 ping 成功
【发布时间】:2011-09-01 09:57:23
【问题描述】:

我认为这需要更改为 while 子句,目前它会等到所有 10000 次 ping 完成,我需要它在 ping 成功时返回。 “say”程序在 OSX 上,它可以让计算机说话。

#!/bin/bash
echo begin ping
if ping -c 100000 8.8.8.8 | grep timeout;
then echo `say timeout`;
else echo `say the internet is back up`;
fi

好的,我无权回答我自己的问题,所以这是我玩过之后的答案:

谢谢,是的,我不知道 $?到目前为止。无论如何,现在我已经做了这个。我喜欢你的不会永远消失,但在我的情况下,我不需要它在它完成之前停止。

#!/bin/bash
intertube=0
echo "begin ping"
while [ $intertube -ne 1 ]; do
        ping -c 3 google.com
        if [ $? -eq  0 ]; then
                echo "ping success";
                say success
                intertube=1;
        else
                echo "fail ping"
        fi
done
echo "fin script"

【问题讨论】:

  • 这与ping 无关,但是您要通过echo“说”来完成什么?您的介绍性段落暗示您正在尝试执行 say 命令,如果您只是 echo 这个词,则不会发生这种情况。
  • @Lawrence,那些是 反引号, 不是引号。他们将执行say 命令并回显其输出。
  • 哎呀,错过了很严重;我很抱歉。虽然我仍然不确定那里正在完成什么; say 从不向标准输出输出任何内容。
  • 不需要$?在您的解决方案中;如果 ping... 工作正常。此外,您可以通过使用 break: while :; 来避免额外的变量。如果 ping 则执行;然后打破;菲;完成
  • 另见:ServerFault: How to ping in linux until host is known?。这似乎有一些非常有希望和简短的答案,它们也适用于 Linux(缺少方便的 -o 选项),而不仅仅是具有该选项的 MacO。

标签: bash shell unix while-loop ping


【解决方案1】:

您可能不应该依赖命令的文本输出来决定这一点,尤其是ping 命令gives you a perfectly good return value:

如果至少从指定主机收到一个响应,则 ping 实用程序返回退出状态为零;如果传输成功但未收到响应,则状态为 2;或来自<sysexits.h> 的另一个值(如果发生错误)。

换句话说,使用类似的东西:

((count = 60))                           # Maximum number to try.
while [[ $count -ne 0 ]] ; do
    ping -c 1 8.8.8.8                    # Try once.
    rc=$?
    if [[ $rc -eq 0 ]] ; then
        ((count = 1))                    # If okay, flag loop exit.
    else
        sleep 1                          # Minimise network storm.
    fi
    ((count = count - 1))                # So we don't go forever.
done

if [[ $rc -eq 0 ]] ; then                # Make final determination.
    echo `say The internet is back up.`
else
    echo `say Timeout.`
fi

【讨论】:

  • count = 1 行应该是 ((count = 1)) 来处理空格。
  • @MSumulong,正确,很难相信我(和其他所有人)在过去三年多的时间里错过了这一点。已修复,并将对 count 的所有分配也保持一致。
  • 非管理员用户在没有等待/睡眠的情况下使用 ping 循环会触发防洪机制,从而导致结果不一致。如果你真的打算淹没网络,那么你可能需要添加-A
【解决方案2】:

您不需要使用 echo 或 grep。你可以这样做:

ping -oc 100000 8.8.8.8 > /dev/null && say "up" || say "down"

【讨论】:

  • 这对我有用:ping -c 2 8.8.8.8 > /dev/null && echo "up" ||回声“下”
  • 标志-c 100000 表示尝试100000 次。如果没有这个标志,它将无休止地重试(你需要中断它)。仍然因为-o它会在第一次成功ping 时返回。
  • 这仅适用于 OSX。 Ping 在 Windows 或 Linux 上没有 -o 标志。
  • 是的,原来的问题和这个答案都假设 macOS。注意点它使用Mac 的say 命令来报告ping 成功。在此答案下的第一条评论中,您将看到在 linux 上使用 psecho 的变体。
  • Linux Ubuntu 18.04 的 ping 没有 -o 选项。有适合我的吗?
【解决方案3】:

这也可以通过超时来完成:

# Ping until timeout or 1 successful packet
ping -w (timeout) -c 1

【讨论】:

  • 正是我想要的。
  • 很奇怪。它向我展示了“-bash: 意外标记 `('" 附近的语法错误”
  • @pupsozeyde 那是因为你不应该包含括号,就像 ping -w 30 -c 1 那样超时 30 秒。
【解决方案4】:

我使用这个 Bash 脚本在 OSX 上每分钟测试一次互联网状态

#address=192.168.1.99  # forced bad address for testing/debugging
address=23.208.224.170 # www.cisco.com
internet=1             # default to internet is up

while true;
do
    # %a  Day of Week, textual
    # %b  Month, textual, abbreviated
    # %d  Day, numeric
    # %r  Timestamp AM/PM
    echo -n $(date +"%a, %b %d, %r") "-- " 
    ping -c 1 ${address} > /tmp/ping.$
    if [[ $? -ne 0 ]]; then
        if [[ ${internet} -eq 1 ]]; then   # edge trigger -- was up now down
            echo -n $(say "Internet down") # OSX Text-to-Speech
            echo -n "Internet DOWN"
        else
            echo -n "... still down"
        fi
        internet=0
    else
        if [[ ${internet} -eq 0 ]]; then     # edge trigger -- was down now up
            echo -n $(say "Internet back up") # OSX Text-To-Speech
        fi
        internet=1
    fi   
    cat /tmp/ping.$ | head -2 | tail -1
    sleep 60 ; # sleep 60 seconds =1 min
done

【讨论】:

    【解决方案5】:

    如果您使用-o 选项,BSD ping(也适用于 macOS)将在收到一个回复​​数据包后退出。

    延伸阅读:https://www.freebsd.org/cgi/man.cgi?query=ping

    编辑paxdiablo makes a very good point 关于使用ping 的退出状态对您有利。我会做类似的事情:

    #!/usr/bin/env bash
    echo 'Begin ping'
    if ping -oc 100000 8.8.8.8 > /dev/null; then
        echo $(say 'timeout')
    else
        echo $(say 'the Internet is back up')
    fi
    

    ping 将发送多达 100,000 个数据包,然后以失败状态退出 - 除非它收到一个回复​​数据包,在这种情况下它以成功状态退出。然后if 将执行相应的语句。

    【讨论】:

    • Linux Ubuntu 18.04 的 ping 没有 -o 选项。有适合我的吗?
    【解决方案6】:

    这是我的单线解决方案:

    screen -S internet-check -d -m -- bash -c 'while ! ping -c 1 google.com; do echo -; done; echo Google responding to ping | mail -s internet-back my-email@example.com'
    

    这会在新的屏幕会话中运行无限 ping,直到有响应,此时它会向 my-email@example.com 发送一封电子邮件。在电子邮件发送到手机的时代很有用。

    (您可能想通过首先运行echo test | mail -s test my-email@example.com 来检查mail 是否正确配置。当然,您可以从done; 开始做任何您想做的事情,敲响铃铛,启动网络浏览器,发挥您的想象力.)

    【讨论】:

      【解决方案7】:

      我喜欢 paxdiablo 的脚本,但想要一个可以无限期运行的版本。此版本运行 ping 直到建立连接,然后打印一条消息。

      echo "Testing..."
      
      PING_CMD="ping -t 3 -c 1 google.com > /dev/null 2>&1"
      
      eval $PING_CMD
      
      if [[ $? -eq 0 ]]; then
          echo "Already connected."
      else
          echo -n "Waiting for connection..."
      
          while true; do
              eval $PING_CMD
      
              if [[ $? -eq 0 ]]; then
                  echo
                  echo Connected.
                  break
              else
                  sleep 0.5
                  echo -n .
              fi
          done
      fi
      

      我还有一个Gist of this script,我会根据需要更新它并进行修复和改进。

      【讨论】:

        猜你喜欢
        • 2017-01-15
        • 1970-01-01
        • 2019-06-18
        • 1970-01-01
        • 1970-01-01
        • 2021-04-07
        • 2017-07-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多