50

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

我可以显示一个消息框,如此处所述显示来自 Windows 批处理文件的弹出/消息框

并且可以通过连续 ping

ping <servername> -t

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

4

12 回答 12

31

问题是查看 ping 是否响应了该脚本的响应。

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

如果我记得检查 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。

于 2010-08-14T22:18:48.550 回答
26

以下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
于 2010-06-16T05:39:16.150 回答
9

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

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

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

于 2016-10-04T10:40:11.263 回答
2

我根据 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。希望这对其他人有帮助。

于 2016-05-27T15:38:00.630 回答
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 >NUL将等待 1 秒,但仅在连接到网络时才有效

于 2016-11-20T08:56:19.277 回答
0

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

于 2010-06-16T05:41:33.310 回答
0

简单版:

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
)
)

)
于 2014-07-01T05:36:40.707 回答
0

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

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

@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
于 2017-05-14T18:15:29.370 回答
0

我稍微修改了 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 个令牌。

于 2021-04-26T13:16:43.357 回答
0

以下@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)
)
于 2021-10-09T19:25:43.140 回答
-1

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

前两个返回 ERRORLEVEL 为 0。

超时返回 ERRORLEVEL 为 1。

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

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

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

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

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

于 2014-10-16T22:57:51.590 回答
-2
#!/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
于 2018-02-07T17:35:36.827 回答