捕获所有可能的 ping 问题的批处理命令 [英] Batch Command to catch all possible ping issues

查看:18
本文介绍了捕获所有可能的 ping 问题的批处理命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于验证 ping 是否在批处理命令中正确返回的问题.目前,我必须通过 3 种不同的方式检查 ping 才能知道服务器实际上已启动.我想将这些组合成一个单一的 ping 命令.我曾尝试使用不同的错误级别或不使用错误级别 0 等.它们都没有捕获所有可能的情况.这是我一直在使用的:

I have a question regarding verifying that a ping is returning properly in a batch command. Currently I have to check a ping 3 different ways to know that the server is in fact up. I want to combine these into one single ping command. I have tried using different error levels or not errorlevel 0 etc. None of them catch all possible scenarios. Here is what I have been using:

Set /p domain=Enter IP address:
set state=up

@ping.exe -n 1 %domain% | find "unreachable" > null && set state=down
if "%state%" == "down" goto :NoServer

@ping.exe -n 1 %domain% | find "TTL expired" > null && set state=down
if "%state%" == "down" goto :NoServer

@ping.exe -n 1 %domain%
if errorlevel 1 goto :NoServer

推荐答案

检查ping命令成功或失败的方法有两种:执行后测试errorlevel或测试命令的输出.对于这两种情况,检查 ipv4 或 ipv6 地址是不一样的.

There are two ways to check the sucess or failure of the ping command: test the errorlevel after execution or test the output of the command. For both cases, it is not the same to check a ipv4 or a ipv6 address.

问题是:ping 的行为如何?它的输出是什么?errorlevel 什么时候设置?

The questions are: how does ping behave?, what is its output? when is errorlevel set?

errorlevel

如果我们使用 ipv6,规则是

If we are working with ipv6, the rules are

  • errorlevel 当所有发送的数据包都没有回复时设置(所有数据包都丢失了)

  • errorlevel is set when there is no reply for all of the sent packets (all packets are lost)

errorlevel 如果对任何发送的数据包有回复,则不设置

errorlevel is not set if there is a reply to any of the sent packets

ipv6 具有一致的行为,检查错误级别是了解机器是否在线的可靠方法.

ipv6 has a consistent behaviour and checking the errorlevel is a reliable way to know if the machine is online.

ipv4 规则不同

  • errorlevel 当至少有一个发送的数据包没有回复时设置

  • errorlevel is set when there is no reply to at least one of the sent packets

errorlevel 没有设置所有发送的数据包都有回复(没有丢包)

errorlevel is not set when there is a reply to all of the sent packets (no packet lost)

但是,在 ipv4 中,ping 同一子网上的不可用机器不会设置 errorlevel,您会得到无法访问"的答案,其中 n 个数据包已发送,n 个已打包接收,0 个数据包丢失,所有数据包都从发送数据包的同一台机器上得到回复.

But, in ipv4, pinging an non available machine on the same subnet does no set the errorlevel, you get an "unreachable" answer, with n packets sent, n packed received, 0 packets lost, all the packets get a reply from the same machine sending the packets.

当机器在同一子网中时,ipv4 中的这种行为会导致错误级别检查失败.

This behaviour in ipv4 when the machine is in the same subnet makes the errorlevel check fail.

在ipv4中如何解决问题?输出检查

可以检查ping命令的输出,如果输出中出现字符串TTL=,则目标机器在线.

The output of the ping command can be checked, if the string TTL= is present in the output, the target machine is online.

ping -n 1 10.0.0.1 | find "TTL=" >nul 
if errorlevel 1 ( 
    echo offline 
) else (
    echo online
)

但是这种在 ipv4 中有效的方法将在 ipv6 中失败,因为该字段未包含在 ping 输出中(并重命名,在 ipv6 中称为 hop limit)

But this approach that works in ipv4 will fail with ipv6 as this field has not been included in the ping output (and renamed, in ipv6 it is called hop limit)

对于通用"解决方案,可以使用这个(改编自之前的答案)(看起来很多代码,但几乎都是注释).ping 操作和输出处理包含在一个子例程中,该子例程使用作为第一个参数传递给批处理文件的地址/主机名调用.

For a "general" solution, this (adapted from a previous answer) can be used (seems a lot of code, but almost all are comments). The ping operation and output handling are wrapped inside a subroutine that is called with the address/host name passed as the first argument to the batch file.

@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%

这篇关于捕获所有可能的 ping 问题的批处理命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆