【问题标题】:How to check if ping responded or not in a batch file如何在批处理文件中检查 ping 是否响应
【发布时间】:2010-06-16 05:27:21
【问题描述】:

我想持续 ping 服务器并在它响应时看到一个消息框,即服务器当前已关闭。我想通过批处理文件来做。

我可以在这里显示一个消息框Show a popup/message box from a Windows batch file

可以连续ping通

ping <servername> -t

但是我如何检查它是否响应?

【问题讨论】:

  • 一般不会给你返回xx字节的数据吗?
  • 但我在问如何在批处理文件的 if 条件下检查它
  • 这个问题已经很流行了(查看了 1000 次),问题和答案的点赞数并不多。这让我猜想访问者来到这个页面是为了别的东西,而不是在这里找到它。换句话说,我猜这个页面出现在一些与这个问题无关的关键字的搜索结果中。我想知道其他内容(或与此问题无关的关键字)是什么,我如何更改此问题的标题,以便节省访问者(期待其他内容)的时间。

标签: command-line batch-file ping


【解决方案1】:

下面的checklink.cmd 程序是一个很好的起点。它依赖于您可以进行单次 ping 的事实,如果成功,输出将包含以下行:

Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),

通过提取标记 5 和 7 并检查它们分别是 "Received""1,",您可以检测到成功。

@setlocal enableextensions enabledelayedexpansion
@echo off
set ipaddr=%1
:loop
set state=down
for /f "tokens=5,6,7" %%a in ('ping -n 1 !ipaddr!') do (
    if "x%%b"=="xunreachable." goto :endloop
    if "x%%a"=="xReceived" if "x%%c"=="x1,"  set state=up
)
:endloop
echo.Link is !state!
ping -n 6 127.0.0.1 >nul: 2>nul:
goto :loop
endlocal

使用您要测试的名称(或 IP 地址)调用它:

checklink 127.0.0.1
checklink localhost
checklink nosuchaddress

请注意,如果您的语言环境不是英语,则必须将 Received 替换为您语言环境中的相应关键字,例如 recibidos 表示西班牙语。执行测试 ping 以发现您的语言环境中使用的关键字。


要仅在状态更改时通知您,您可以使用:

@setlocal enableextensions enabledelayedexpansion
@echo off
set ipaddr=%1
set oldstate=neither
:loop
set state=down
for /f "tokens=5,7" %%a in ('ping -n 1 !ipaddr!') do (
    if "x%%a"=="xReceived" if "x%%b"=="x1," set state=up
)
if not !state!==!oldstate! (
    echo.Link is !state!
    set oldstate=!state!
)
ping -n 2 127.0.0.1 >nul: 2>nul:
goto :loop
endlocal

但是,正如 Gabe 在评论中指出的那样,您可以只使用 ERRORLEVEL,因此上面第二个脚本的等效项变为:

@setlocal enableextensions enabledelayedexpansion
@echo off
set ipaddr=%1
set oldstate=neither
:loop
set state=up
ping -n 1 !ipaddr! >nul: 2>nul:
if not !errorlevel!==0 set state=down
if not !state!==!oldstate! (
    echo.Link is !state!
    set oldstate=!state!
)
ping -n 2 127.0.0.1 >nul: 2>nul:
goto :loop
endlocal

【讨论】:

  • 非常感谢@paxdiablo!你能帮我修改一下,这样我只能在服务器启动时看到一个消息框吗?显示消息框的命令是msg "%username%" Link is up,这个命令适用于我在 Windows 7 上。
  • 你要做很多工作,而不是只检查%ERRORLEVEL%
  • 这是一个很好的观点,@Gabe,我已将其合并到脚本中。
  • ping 收到“目标主机无法访问”回复时,%errorlevel% 的值似乎为 0。
  • 不错的解决方案,除了输出在使用另一种语言的系统上被翻译。所以检查“已收到”是不可能的。我想检查三个数字是否为 1、1 和 0 也应该可以。
【解决方案2】:

这是我发现的一些东西:

:pingtheserver
ping %input% | find "Reply" > nul
if not errorlevel 1 (
    echo server is online, up and running.
) else (
    echo host has been taken down wait 3 seconds to refresh
    ping 1.1.1.1 -n 1 -w 3000 >NUL
    goto :pingtheserver
) 

请注意,ping 1.1.1.1 -n -w 1000 &gt;NUL 将等待 1 秒,但仅在连接到网络时才有效

【讨论】:

  • 这比许多其他的更简单并且对我有用。除非我将find "Reply" 更改为find "time=",因为有时它会找到Reply from X.X.X.X: Destination host unreachable. 并将其视为成功,而我希望它是失败的。
【解决方案3】:

我知道这是一个旧线程,但我想测试我的系统上是否有机器启动,除非我有误解,如果我的路由器报告地址无法访问,上述方法都不起作用。我使用的是批处理文件而不是脚本,因为我想在几乎任何 WIN 机器上“亲吻”。所以我使用的方法是执行多个 ping 并测试“Lost = 0”,如下所示

ping -n 2 %pingAddr% | find /I "Lost = 0"  
if %errorlevel% == 0 goto OK

我没有对此进行严格的测试,但到目前为止它对我来说已经完成了这项工作

【讨论】:

    【解决方案4】:

    问题是看 ping 是否响应了这个脚本的响应。

    但是,如果您收到 Host Unreachable 消息,这将不起作用,因为这将返回 ERRORLEVEL 0 并通过此脚本中使用的 Received = 1 的检查,从脚本返回 Link is UP。当 ping 传送到目标 notwork 但找不到远程主机时,会发生 Host Unreachable。

    如果我记得检查 ping 是否成功的正确方法是使用 Find 查找字符串“TTL”。

    @echo off
    cls
    set ip=%1
    ping -n 1 %ip% | find "TTL"
    if not errorlevel 1 set error=win
    if errorlevel 1 set error=fail
    cls
    echo Result: %error%
    

    这不适用于 IPv6 网络,因为 ping 在接收来自 IPv6 地址的回复时不会列出 TTL。

    【讨论】:

    • 使用 ping -4 参数强制使用 IPv4。很好的解决方案,谢谢!
    【解决方案5】:

    我根据paxdiablo的帖子做了一个变体解决方案

    将以下代码放入Waitlink.cmd

    @setlocal enableextensions enabledelayedexpansion
    @echo off
    set ipaddr=%1
    :loop
    set state=up
    ping -n 1 !ipaddr! >nul: 2>nul:
    if not !errorlevel!==0 set state=down
    echo.Link is !state!
    if "!state!"=="up" (
      goto :endloop
    )
    ping -n 6 127.0.0.1 >nul: 2>nul:
    goto :loop
    :endloop
    endlocal
    

    例如从另一个像这样的批处理文件中使用它

    call Waitlink someurl.com
    net use o: \\someurl.com\myshare
    

    只有在 ping 成功时才会返回对 waitlink 的调用。感谢 paxdiablo 和 Gabe。希望这对其他人有帮助。

    【讨论】:

      【解决方案6】:
      #!/bin/bash
      logPath="pinglog.txt"
      
      while(true)
            do
                # refresh the timestamp before each ping attempt
                theTime=$(date -Iseconds)
      
                # refresh the ping variable
                ping google.com -n 1
      
                  if [ $? -eq 0 ] 
                  then
                       echo $theTime + '| connection is up' >> $logPath
                  else
                       echo $theTime + '| connection is down' >> $logPath
                fi
                  Sleep 1
                   echo ' '
            done
      

      【讨论】:

      • 问题是关于windows批处理文件而不是bash
      【解决方案7】:

      您可以不带“-t” ping 并检查 ping 的退出代码。无应答时报告失败。

      【讨论】:

      • 我们程序员可以比英语更快地阅读和理解代码;)。开个玩笑。
      • OP 可能想要设置批处理脚本运行,然后在机器上执行其他操作,只是在状态更改时收到警报。不是坐着看每个 ping 的回复结果。
      【解决方案8】:

      简单版:

      for /F "delims==, tokens=4" %a IN ('ping -n 2 127.0.0.1 ^| findstr /R "^Packets: Sent =.$"') DO (
      
      if %a EQU 2 (
      echo Success
      ) ELSE (
      echo FAIL
      )
      
      )
      

      但有时第一个 ping 会失败,而第二个会正常工作(反之亦然),对吗?因此,我们希望在成功返回至少一个 ICMP 回复时获得成功:

      for /F "delims==, tokens=4" %a IN ('ping -n 2 192.168.1.1 ^| findstr /R "^Packets: Sent =.$"') DO (
      
      if %a EQU 2 (
      echo Success
      ) ELSE (
      if %a EQU 1 (
      echo Success
      ) ELSE (
      echo FAIL
      )
      )
      
      )
      

      【讨论】:

        【解决方案9】:

        我希望这对某人有所帮助。在检查各个路径之前,我使用这一点逻辑来验证网络共享是否响应。它应该处理 DNS 名称和 IP 地址

        文本文件中的有效路径是 \192.168.1.2\'文件夹'或\NAS\'文件夹'

        @echo off
        title Network Folder Check
        
        pushd "%~dp0"
        :00
        cls
        
        for /f "delims=\\" %%A in (Files-to-Check.txt) do set Server=%%A
            setlocal EnableDelayedExpansion
                ping -n 1 %Server% | findstr TTL= >nul 
                    if %errorlevel%==1 ( 
                        ping -n 1 %Server% | findstr "Reply from" | findstr "time" >nul
                            if !errorlevel!==1 (echo Network Asset %Server% Not Found & pause & goto EOF)
                    )
        :EOF
        

        【讨论】:

          【解决方案10】:

          我稍微修改了 PaxDiablo 的代码,以更好地适应我正在做的事情,并认为我会分享。我的目标是遍历 IP 地址列表以查看是否有任何剩余,并且此代码将在周末的最后一个班次结束时运行,以检查是否每个人都按照说明关闭所有 PC 之前他们回家了。

          由于在 for 循环中使用 goto 打破了所有 for 循环,而不仅仅是最低的嵌套 for 循环,PaxDiablo 的代码在到达无法访问的 IP 地址时停止处理进一步的 IP 地址。我发现我可以添加第二个变量来跟踪它无法访问而不是退出循环,现在这段代码对我来说运行得很好。

          我将文件保存为 CheckPCs.bat,虽然我猜这不是正确的编码习惯,但我确实在代码下方列出了 IP 地址以及在我的情况下是 PC 的物理位置的描述。正如其他人所提到的,您必须为其他本地化和 IPV6 进一步修改代码。

          @setlocal enableextensions enabledelayedexpansion
          @echo off
          for /f "tokens=2,3 delims=/ skip=16" %%i in (CheckPCs.bat) do (
          set ipaddr=%%i
          set state=shut down
          set skip=0
          for /f "tokens=5,6,7" %%a in ('ping -n 1 !ipaddr!') do (
              if "x%%b"=="xunreachable." set skip=1
              if !skip!==0 if "x%%a"=="xReceived" if "x%%c"=="x1,"  set state=still on
          )
          echo %%i %%j is !state!
          
          )
          pause
          endlocal
          
          rem /IP ADDRESS0/COMPUTER NAME0
          rem /IP ADDRESS1/COMPUTER NAME1
          

          如果您确实需要修改此代码,请注意:

          for /f "tokens=2,3 delims=/ skip=16" %%i in (CheckPCs.bat) do (
          

          for 循环每次处理 CheckPCs.bat 一行。 Skip 告诉它忽略前 16 行并直接访问 IP 地址。我没有特殊原因使用 / 作为分隔符,但请注意,如果您要 ping 网址而不是 IP,则必须更改分隔符。管道字符之类的东西|会工作。当然,由于该行被 rem 注释掉,rem 成为第一个标记,这意味着我只想使用标记 2 和 3,它们将是 IP 地址和 PC 描述。后一个字段是可选的,您只需修改代码即可将其删除。

          您可能应该修改用于 state 的术语,并且 echo %%i %%j is !state!以便术语对您来说清晰简洁。如果您想在某处记录状态,您可以通过将 >> file.txt 附加到该行将其输入文本文件。在这种情况下,您可能还想添加日期/时间。

          最后,经过适当编码培训的人可能知道,带有标记的批处理 for 循环的工作方式(简单来说)是文本的每个部分在每个分隔符处拆分,默认为空格,然后它被分配给一个 %% 变量,其名称以您指定的任何字符开头,然后增加 ascii 字符列表。这意味着如果我指定从 %%i 开始,下一个标记将是 %%j,然后是 %%k,依此类推。如果我使用 %%B,接下来是 %%C,然后是 %%D 等等。我阅读的关于该主题的每个线程最多可以有 31 个标记。

          【讨论】:

            【解决方案11】:

            以下 @Dan W 回答:

            @echo off
            
            set Server=192.168.0.18
            setlocal EnableDelayedExpansion
            :checkhost
            ping -n 1 %Server% | findstr TTL= >nul 
            if %errorlevel%==1 ( 
                ping -n 1 %Server% | findstr "Reply from" | findstr "time" >nul
                if !errorlevel!==1 (echo Network Asset %Server% Not Found & goto checkhost)
            )
            

            【讨论】:

              【解决方案12】:

              我已经看到 ping 的三个结果 - 我们“想要”IP 回复的结果,“主机无法访问”和“超时”(不确定确切的措辞)。

              前两个返回 ERRORLEVEL 为 0。

              超时返回 ERRORLEVEL 为 1。

              是否可能返回其他结果和错误级别? (除了使用返回允许的开关和错误级别 1 的无效开关。)

              显然 Host Unreachable 可以使用之前发布的方法之一(尽管很难弄清楚何时有人回复他们正在编写代码的情况)但是超时是否以可以解析的类似方式返回?

              一般来说,如何知道 ping 的结果的哪一部分可以被解析? (即,为什么 Sent 和/或 Received 和/或 TTL 可以解析,但主机不可达?

              哦,还有 iSid,也许没有多少赞成票,因为阅读本文的人没有足够的分数。所以他们得到他们的问题回答(或不回答)然后离开。

              我没有发布以上内容作为答案。应该是评论,但我没有看到那个选项。

              【讨论】:

              • 每个答案和问题下方都有一个“添加评论”链接(蓝色,全部小写,靠近分隔帖子的行)。请根据他们适用的相应问题/答案将上面的 cmets 复制并粘贴到 cmets 中。 -1
              猜你喜欢
              • 1970-01-01
              • 2011-05-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-04-27
              • 2011-08-09
              • 2013-01-19
              相关资源
              最近更新 更多