有两种方法来检查ping命令的研制成功或失败:测试错误级别执行后或测试命令的输出。对于这两种情况,检查ipv4或ipv6地址是不一样的。
问题是:ping
如何表现?,它的输出是什么? errorlevel
是什么时候设置的?
的errorlevel
如果我们与IPv6工作,规则是当存在对所有发送的数据包没有回复(所有数据包丢失)
ipv6具有一致的行为,并检查errorlevel是知道机器是否在线的可靠方法。
在IPv4中的规则不同
但是,在IPv4中,在同一个子网查验的非可用机器并没有固定的日e errorlevel
,你会得到一个“无法达到”的答案,n packets sent, n packed received, 0 packets lost
,所有的数据包都会从发送数据包的同一台机器得到答复。
当机器位于同一子网中时,此行为在ipv4中使错误级别检查失败。
如何解决IPv4中的问题?输出检查
可以检查ping
命令的输出,如果输出中存在字符串TTL=
,目标机器处于联机状态。
ping -n 1 10.0.0.1 | find "TTL=" >nul
if errorlevel 1 (
echo offline
) else (
echo online
)
但是,这种方法是在IPv4中可以作为这个领域还没有被列入平输出将与IPv6的失败(并改名,在IPv6中它被称为跳限制)
对于“一般”解决方案,可以使用(从先前的答案改编而来)(似乎有很多代码,但几乎都是注释)。 ping
操作和输出处理被封装在一个子例程中,该子例程使用作为批处理文件的第一个参数传递的地址/主机名称进行调用。
@echo off
setlocal enableextensions disabledelayedexpansion
if "%~1"=="" goto :eof
call :isOnline "%~1"
if not errorlevel 1 (echo ONLINE) else (echo OFFLINE)
endlocal
exit /b
:isOnline address pingCount
setlocal enableextensions disabledelayedexpansion
:: send only one ping packed unless it is indicated to send more than one
set /a "pingCount=0", "pingCount+=%~2" >nul 2>nul
if %pingCount% lss 1 set "pingCount=1"
:: a temporary file is needed to capture ping output for later processing
set "tempFile=%temp%\%~nx0.%random%.tmp"
:: ping the indicated address getting command output and errorlevel
ping -w 1000 -n %pingCount% "%~1" > "%tempFile%" && set "pingError=" || set "pingError=1"
::
:: When pinging, the behaviours of ipv4 and ipv6 are different
::
:: we get errorlevel = 1 when
:: ipv4 - when at least one packet is lost. When sending more than one packet
:: the easiest way to check for reply is search the string "TTL=" in
:: the output of the command.
:: ipv6 - when all packet are lost.
::
:: we get errorlevel = 0 when
:: ipv4 - all packets are received. BUT pinging a inactive host on the same
:: subnet result in no packet lost. It is necessary to check for "TTL="
:: string in the output of the ping command
:: ipv6 - at least one packet reaches the host
::
:: We can try to determine if the input address (or host name) will result in
:: ipv4 or ipv6 pinging, but it is easier to check the result of the command
::
:: +--------------+-------------+
:: | TTL= present | No TTL |
:: +-----------------------+--------------+-------------+
:: | ipv4 errorlevel 0 | OK | ERROR |
:: | errorlevel 1 | OK | ERROR |
:: +-----------------------+--------------+-------------+
:: | ipv6 errorlevel 0 | | OK |
:: | errorlevel 1 | | ERROR |
:: +-----------------------+----------------------------+
::
:: So, if TTL= is present in output, host is online. If TTL= is not present,
:: errorlevel is 0 and the address is ipv6 then host is online. In the rest
:: of the cases host is offline.
::
:: To determine the ip version, a regular expresion to match a ipv6 address is
:: used with findstr. As it will be only tested in the case of no errorlevel,
:: the ip address will be present in ping command output.
set "exitCode=1"
>nul 2>nul (
find "TTL=" "%tempFile%" && (set "exitCode=0") || (
if not defined pingError (
findstr /r /c:" [a-f0-9:][a-f0-9]*:[a-f0-9:%%]*[a-f0-9]: " "%tempFile%" && set "exitCode=0"
)
)
del /q "%tempFile%"
)
:: cleanup and return errorlevel: 0=online , 1=offline
endlocal & exit /b %exitCode%
> tempfile是做什么的?我会假设它创建一个临时文件,但为什么? – Konan
'>'是'重定向器'。与'''重定向命令的输出一样,作为下一个输入的输入,'>'将输出重定向到一个新文件(或者替换现有文件)'>>'将输出重定向到一个新文件(或者附加一个新文件现有文件)和'<'重定向来自文件而不是来自键盘的输入。 – Magoo
谢谢,这是很好的信息! – Konan