我可以像这里所说的那样显示一个消息框:Show a popup/message box from a Windows batch file 并且可以通过以下方式持续进行ping操作:
ping <servername> -t
但是我该如何检查它是否已经响应?
ping <servername> -t
这个问题是想要查看 ping 命令是否有响应,而这个脚本可以实现。
然而,如果你收到了“目标主机不可达”的消息,这个脚本就不能正常工作了。因为它返回 ERRORLEVEL 0 并且符合本脚本中用于检查接收 = 1 的条件,从而返回“连接已建立(Link is UP)”。当 ping 命令传递到目标网络但无法找到远程主机时,就会出现“目标主机不可达”的情况。
如果我没记错的话,检查 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操作,并且如果成功,则输出将包含以下行:checklink.cmd
program is a good place to start. It relies on the fact that you can do a single-shot ping and that, if successful, the output will contain the line: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
%ERRORLEVEL%
! - Gabeping
收到“目标主机不可达”的回复时,似乎会返回 %errorlevel%
为0。 - Owen我知道这是一个老的线程,但我想测试一台机器是否在我的系统上运行,除非我误解了,以上所有方法都不起作用,如果我的路由器报告某个地址不可达。我使用批处理文件而不是脚本,因为我希望在几乎任何WIN机器上都能够"KISS"。所以我采用的方法是进行多次ping,并按如下方式测试"Lost = 0"
ping -n 2 %pingAddr% | find /I "Lost = 0"
if %errorlevel% == 0 goto OK
我还没有进行过严格的测试,但目前来看它对我很有效
@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
这里有一些我找到的内容:
: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秒钟,但只有在连接到网络时才能正常工作。@setlocal enableextensions enabledelayedexpansion
@echo off
set ipaddr=8.8.8.8
:loop
for /f "tokens=5,6,7" %%a in ('ping -n 1 !ipaddr!') do (
if "x%%b"=="xunreachable." goto :endloop
if "x%%b"=="xtimed out." goto :endloop
if "x%%a"=="xReceived" if "x%%c"=="x1," goto :up
)
:endloop
set state=Down
echo.Connection is !state!
ping -n 2 127.0.0.1 >nul: 2>nul:
echo starting Repairing at %date% %time%>>D:\connection.log
call repair.cmd>>D:\connection.log
ping -n 10 127.0.0.1 >nul: 2>nul:
goto :loop
endlocal
:up
set state=Up
echo.Connection is !state!
ping -n 6 127.0.0.1 >nul: 2>nul:
cls
goto :loop
endlocal
如果从Google DNS没有ping响应,则启动修复过程,我为此设置了静态IP,但与动态IP也应该可以工作。
repair.cmd:
route -f
ipconfig /release
ipconfig /renew
arp -d *
nbtstat -R
nbtstat -RR
ipconfig /flushdns
ipconfig /registerdns
cls
致以最好的祝福
希望这能帮助到某些人。我使用这个逻辑来验证网络共享是否响应,然后再检查各个路径。它应该处理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
简单版本:
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
)
)
)
我稍微修改了PaxDiablo的代码,使其更适合我的需求,并想与大家分享。我的目标是循环遍历一个IP地址列表,查看是否有任何一个处于开启状态,这段代码将在周末最后一班次结束时运行,以检查每个人是否遵守了在下班前关闭所有PC的指示。
由于在for循环中使用goto会跳出所有for循环,而不仅仅是最低嵌套的for循环,因此PaxDiablo的代码在到达无法访问的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描述。后一个字段是可选项,你只需要修改代码来删除它。
您应该修改用于状态和回显%%i %%j is !state!的术语,以使术语对您清晰明了。如果您想在某个地方记录状态,则可以通过附加>> file.txt将其输入到文本文件中。在那种情况下,您可能还想添加日期/时间。
最后,那些接受过编程适当培训的人可能知道,批处理循环与令牌的工作方式(简单来说)是将文本的每个部分在每个定界符处分割,默认为空格,然后将其分配给一个%%变量,其名称从您指定的任何字符开始,然后沿着ASCII字符列表递增。这意味着如果我指定从%%i开始,下一个标记将是%%j,然后是%%k等等。如果我使用%%B,则下一个将是%%C,然后是%%D等等。根据我在该主题上阅读的另一个线程,每个线程最多可以有31个令牌。