IsmailS
IsmailS

Reputation: 10863

How to check if ping responded or not in a batch file

I want to continuously ping a server and see a message box when ever it responds i.e. server is currently down. I want to do it through batch file.

I can show a message box as said here Show a popup/message box from a Windows batch file

and can ping continuously by

ping <servername> -t

But how do I check if it responded or not?

Upvotes: 55

Views: 232317

Answers (14)

George Robinson
George Robinson

Reputation: 2125

Testing for the ERRORLEVEL set by ping is useless because in some situations it sets the ERRORLEVEL to zero (success) even when it has not received any valid replies from the remote host !!!

However, the method described below is solid, portable and works with:

  1. Translations into all other languages of e.g.: "ms", "TTL", "Reply from", "loss", "Unreachable", "Received", etc..., including into Russian and into Chinese.
  2. Pinging an IPv4 address.
  3. Pinging an IPv6 address.
  4. Situations in which the error "General failure." occurs.
  5. Pinging an address that returns "Request timed out."
  6. Pinging an address that returns "Destination host unreachable."
  7. Pinging a resolvable alphanumeric host.
  8. Pinging an unresolvable alphanumeric host, which causes the "Ping request could not find host UnresolvableHost..." error to be returned.
@echo off

FOR /F %%A IN ('ping %1 -n 1 ^| findstr /C:^= ^| find /c /v ""') DO (SET "res=%%A")

if %res% GEQ 2 (
    echo SUCCESS.
) else (
    echo FAILURE.
)

If you save the code above to a file named e.g. pingtest.bat, you can use it like this:

pingtest 192.168.1.1

This method takes advantage of the presence of equal signs in the strings bytes= which are not affected by translations to other languages and do not occur in unsuccessful ping/echo results.

Also, modifying the switch -n 1 to e.g. -n 6 allows you to get a qualitative result in the variable %res% reflecting the quality of the connection.

With the code below, you can normalize the result in the variable %res% so it becomes 0 upon failure ...and upon success - the number of successful pings:

@echo off

FOR /F %%A IN ('ping %1 -n 6 ^| findstr /C:^= ^| find /c /v ""') DO (SET "res=%%A")

if %res% GEQ 2 (
    SET /A "res=%res%-2"
) else (
    SET "res=0"
)

ECHO The number of successful pings is %res%

Upvotes: 1

Rickz
Rickz

Reputation: 21

thanks to @paxdiablo and @Jan Lauridsen this is my modification to check and IP (local machine), good for case which connection is dropped either from dhcp server or any other issue, tested Under WinXP PRO SP3

checkconnection.cmd:

@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

if no ping response from google DNS then start repair, i had static IP set for this purpose but it should work with dinamic as well.

repair.cmd:

route -f
ipconfig /release
ipconfig /renew
arp -d *
nbtstat -R
nbtstat -RR
ipconfig /flushdns
ipconfig /registerdns
cls

My Best Regards

Upvotes: 1

sys7em
sys7em

Reputation: 131

Following @Dan W answer:

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

Upvotes: 0

Burmeind
Burmeind

Reputation: 11

I've modified PaxDiablo's code slightly to better fit with what I was doing and thought I'd share. My objective was to loop through a list of IP addresses to see if any were left on, and this code is to be run at the end of the last shift of the weekend to check if everyone is following the instructions to shut down all PCs before they go home.

Since using a goto in a for loop breaks out of all for loops not just the lowest nested for loop, PaxDiablo's code stopped processing further IP addresses when it got to one that was unreachable. I found that I could add a second variable to track that it was unreachable rather than exiting the loop and now this code is now running perfectly for me.

I have the file saved as CheckPCs.bat and though I'm guessing it's not proper coding practice, I do have the IP addresses listed below the code along with a description which in my case is the physical location of the PC. As mentioned by others you will have to modify the code further for other localizations and for 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

Some notes if you do need to modify this code:

for /f "tokens=2,3 delims=/ skip=16" %%i in (CheckPCs.bat) do (

The for loop is processing CheckPCs.bat one line at a time. Skip is telling it to ignore the first 16 lines and go straight to the IP addresses. I'm using / as a delimiter for no particular reason but note that if you are pinging web addresses instead of IP, you'll have to change the delimiter. Something like the pipe character | would work. Of course since the line is commented out with rem, rem becomes the first token which means I only want to work with tokens 2 and 3 which will be the IP address and PC description. The latter field is optional, you'd just have to modify the code to remove it.

You should probably modify the terminology used for state and for echo %%i %%j is !state! so that the terminology is clear and concise for you. If you want to record the state somewhere, you can just feed it into a text file by appending >> file.txt to the line. You might want to also add a date/time in that case.

Lastly, something people with proper training in coding these might know, the way a batch for loop with tokens works (in simple terms) is each section of the text is split up at each delimiter, the default being space, and then it is assigned to a %% variable whose name begins at whichever character you specify and then increases up the ascii character list. This means if I specify to start at %%i, the next token will be %%j, then %%k and so on. If I used %%B, next would be %%C, then %%D etc. There can be a maximum of 31 tokens per another thread I read on the topic.

Upvotes: 0

Tal
Tal

Reputation: 194

#!/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

Upvotes: -2

Dan W
Dan W

Reputation: 1

I hope this helps someone. I use this bit of logic to verify if network shares are responsive before checking the individual paths. It should handle DNS names and IP addresses

A valid path in the text file would be \192.168.1.2\'folder' or \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

Upvotes: 0

paxdiablo
paxdiablo

Reputation: 881403

The following 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),

By extracting tokens 5 and 7 and checking they're respectively "Received" and "1,", you can detect the success.

@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

Call it with the name (or IP address) you want to test:

checklink 127.0.0.1
checklink localhost
checklink nosuchaddress

Take into account that, if your locale is not English, you must replace Received with the corresponding keyword in your locale, for example recibidos for Spanish. Do a test ping to discover what keyword is used in your locale.


To only notify you when the state changes, you can use:

@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

However, as Gabe points out in a comment, you can just use ERRORLEVEL so the equivalent of that second script above becomes:

@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

Upvotes: 30

Juggler
Juggler

Reputation: 49

Here's something I found:

: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
) 

Note that ping 1.1.1.1 -n -w 1000 >NUL will wait 1 second but only works when connected to a network

Upvotes: 2

Bigrog
Bigrog

Reputation: 101

I know this is an old thread, but I wanted to test if a machine was up on my system and unless I have misunderstood, none of the above works if my router reports that an address is unreachable. I am using a batch file rather than a script because I wanted to "KISS" on pretty much any WIN machine. So the approach I used was to do more than one ping and test for "Lost = 0" as follows

ping -n 2 %pingAddr% | find /I "Lost = 0"  
if %errorlevel% == 0 goto OK

I haven't tested this rigorously but so far it does the job for me

Upvotes: 10

Jan Lauridsen
Jan Lauridsen

Reputation: 586

I have made a variant solution based on paxdiablo's post

Place the following code in 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

For example use it from another batch file like this

call Waitlink someurl.com
net use o: \\someurl.com\myshare

The call to waitlink will only return when a ping was succesful. Thanks to paxdiablo and Gabe. Hope this helps someone else.

Upvotes: 2

Phil Reinemann
Phil Reinemann

Reputation: 1

I've seen three results to a ping - The one we "want" where the IP replies, "Host Unreachable" and "timed out" (not sure of exact wording).

The first two return ERRORLEVEL of 0.

Timeout returns ERRORLEVEL of 1.

Are the other results and error levels that might be returned? (Besides using an invalid switch which returns the allowable switches and an errorlevel of 1.)

Apparently Host Unreachable can use one of the previously posted methods (although it's hard to figure out when someone replies which case they're writing code for) but does the timeout get returned in a similar manner that it can be parsed?

In general, how does one know what part of the results of the ping can be parsed? (Ie, why might Sent and/or Received and/or TTL be parseable, but not host unreachable?

Oh, and iSid, maybe there aren't many upvotes because the people that read this don't have enough points. So they get their question answered (or not) and leave.

I wasn't posting the above as an answer. It should have been a comment but I didn't see that choice.

Upvotes: -1

damian1baran
damian1baran

Reputation: 1397

Simple version:

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
)

)

But sometimes first ping just fail and second one work (or vice versa) right? So we want to get success when at least one ICMP reply has been returned successfully:

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
)
)

)

Upvotes: 0

Lukasz
Lukasz

Reputation: 623

The question was to see if ping responded which this script does.

However this will not work if you get the Host Unreachable message as this returns ERRORLEVEL 0 and passes the check for Received = 1 used in this script, returning Link is UP from the script. Host Unreachable occurs when ping was delivered to target notwork but remote host cannot be found.

If I recall the correct way to check if ping was successful is to look for the string 'TTL' using Find.

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

This wont work with IPv6 networks because ping will not list TTL when receiving reply from IPv6 address.

Upvotes: 36

Rotsor
Rotsor

Reputation: 13783

You can ping without "-t" and check the exit code of the ping. It reports failure when there is no answer.

Upvotes: 0

Related Questions