我想连续 ping 服务器并在它响应时看到一个消息框,即服务器当前已关闭。我想通过批处理文件来完成。
我可以显示一个消息框,如此处所述显示来自 Windows 批处理文件的弹出/消息框
并且可以通过连续 ping
ping <servername> -t
但是我如何检查它是否响应?
我想连续 ping 服务器并在它响应时看到一个消息框,即服务器当前已关闭。我想通过批处理文件来完成。
我可以显示一个消息框,如此处所述显示来自 Windows 批处理文件的弹出/消息框
并且可以通过连续 ping
ping <servername> -t
但是我如何检查它是否响应?
问题是查看 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。
以下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
我知道这是一个旧线程,但我想测试我的系统上是否有机器启动,除非我有误解,否则如果我的路由器报告地址无法访问,上述方法都不起作用。我使用的是批处理文件而不是脚本,因为我想在几乎任何 WIN 机器上“亲吻”。所以我使用的方法是执行多个 ping 并测试“Lost = 0”,如下所示
ping -n 2 %pingAddr% | find /I "Lost = 0"
if %errorlevel% == 0 goto OK
我没有对此进行严格测试,但到目前为止它为我完成了这项工作
我根据 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。希望这对其他人有帮助。
这是我发现的东西:
: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 秒,但仅在连接到网络时才有效
您可以不带“-t” ping 并检查 ping 的退出代码。无应答时报告失败。
简单版:
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
)
)
)
我希望这可以帮助别人。在检查各个路径之前,我使用这一点逻辑来验证网络共享是否响应。它应该处理 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
我稍微修改了 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 个令牌。
以下@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)
)
我已经看到了 ping 的三个结果 - 我们“想要”IP 回复的结果,“主机无法访问”和“超时”(不确定确切的措辞)。
前两个返回 ERRORLEVEL 为 0。
超时返回 ERRORLEVEL 为 1。
是否可能返回其他结果和错误级别?(除了使用返回允许的开关和错误级别 1 的无效开关。)
显然 Host Unreachable 可以使用先前发布的方法之一(尽管很难弄清楚何时有人回复他们正在编写代码的情况)但是超时是否以可以解析的类似方式返回?
一般来说,如何知道 ping 结果的哪一部分可以被解析?(即,为什么 Sent 和/或 Received 和/或 TTL 是可解析的,但不是主机不可访问?
哦,还有 iSid,也许没有多少赞成票,因为阅读本文的人没有足够的分数。所以他们得到他们的问题回答(或不回答)然后离开。
我没有发布上述内容作为答案。它应该是一个评论,但我没有看到那个选择。
#!/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