Batch Script on 2008 server - If Ping successful then

前端 未结 3 1287
耶瑟儿~
耶瑟儿~ 2020-12-21 23:34

I am attempting to write a script that will check to see if a computer is on my LAN before running the rest of my script. It is a simple backup script using robocopy

相关标签:
3条回答
  • The "problem" with your code is the management of the errorlevel to determine if the machine is or not online.

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

    If we are working with ipv6, the rules are

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

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

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

    In ipv4 the rules are different

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

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

    But 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.

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

    How to solve the problem in ipv4?

    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
    )
    

    For a "general" solution, this (adapted from a previous answer) can be used (seems a lot of code, but almost all are comments)

    @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%
    
    0 讨论(0)
  • 2020-12-22 00:09

    You could just check for the presence of your remote directory:

    IF EXIST "\\%machine%\Share\To\Check" (
        ECHO %machine% is available.
    ) ELSE (
        ECHO %machine% is not available.
    )
    
    0 讨论(0)
  • 2020-12-22 00:09

    Thanks to you both. I tried both but in the end this is what worked for me

    set machine=userbox
    ping -n 1 %machine% | find "TTL=" >nul
    IF errorlevel 1 (
    echo "Computer Not On" %date% %time% > c:\scripts\%machine%-computeroff.log
    ) ELSE (
    robocopy source destination
    shutdown.exe /s /m \\%machine% /c "Mandatory Shutdown in progress. You have 10 minutes" /t 600
    echo "shutdown command given" %date% %time% > c:\scripts\shutdown-%machine%.log 
    

    Cheers

    0 讨论(0)
提交回复
热议问题