Command line 如何在批处理文件中检查ping是否响应

Command line 如何在批处理文件中检查ping是否响应,command-line,batch-file,ping,Command Line,Batch File,Ping,我想持续ping一个服务器,并在它响应时看到一个消息框,即服务器当前已关闭。我想通过批处理文件来完成它 我可以显示一个消息框,如这里所说 并且可以通过 ping <servername> -t ping-t 但是如何检查它是否响应?下面的checklink.cmd程序是一个很好的开始。它依赖于这样一个事实,即您可以执行单次ping,并且如果成功,输出将包含以下行: Packets: Sent = 1, Received = 1, Lost = 0 (0% loss), 通过提取

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

我可以显示一个消息框,如这里所说

并且可以通过

ping <servername> -t
ping-t

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

下面的
checklink.cmd
程序是一个很好的开始。它依赖于这样一个事实,即您可以执行单次ping,并且如果成功,输出将包含以下行:

Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
通过提取令牌5和令牌7并分别检查它们是否已
“接收”
“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

您可以不使用“-t”进行ping,并检查ping的退出代码。当没有答案时,它会报告失败。

问题是看ping是否响应了此脚本的响应

但是,如果您收到主机不可访问消息,则此操作将不起作用,因为此消息返回ERRORLEVEL 0并通过了此脚本中使用的Received=1检查,返回的链接已从脚本启动。当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网络,因为当收到来自IPv6地址的回复时,ping不会列出TTL。

简单版本:

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失败,第二个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
)
)

)

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

前两个返回的ERRORLEVEL为0

超时返回错误级别1

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

显然,Host Unreachable可以使用之前发布的方法之一(尽管很难确定某人何时回复他们正在为哪种情况编写代码),但超时的返回方式是否与可以解析超时的方式类似

一般来说,如何知道ping结果的哪一部分可以被解析?(即,为什么发送和/或接收和/或TTL是可解析的,而不是无法访问主机

哦,还有伊希德,可能因为读到这篇文章的人没有足够的分数,所以他们的问题得到了回答(或者没有),然后离开


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

我根据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

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

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

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

我还没有对此进行严格测试,但到目前为止,它确实适合我

我发现:

: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秒,但仅在连接到网络时才起作用

我希望这对某人有所帮助。在检查各个路径之前,我使用此逻辑验证网络共享是否响应。它应该处理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

我已经稍微修改了PaxDiablo的代码,以更好地适应我正在做的事情,并认为我会与大家分享。我的目标是循环查看IP地址列表,看看是否有保留的IP地址,该代码将在周末最后一班结束时运行,以检查是否每个人都按照指示在回家前关闭所有PC。

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

我将文件另存为CheckPCs.bat,虽然我猜这不是正确的编码实践,但我确实有代码下面列出的IP地址以及一个描述,在我的情况下,该描述是电脑的物理位置。正如其他人所提到的,您将不得不为其他本地化和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的是web地址而不是IP,则必须更改分隔符。类似于管道字符|的内容可以使用。当然当然,因为这行是用rem注释掉的,所以rem成为第一个标记,这意味着我只想使用它
for /f "tokens=2,3 delims=/ skip=16" %%i in (CheckPCs.bat) do (