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

13

54

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?

Theta answered 16/6, 2010 at 5:27 Comment(3)
Does it not generally give you returned with xx bytes of data?Wrench
But I was asking how to check it within an if condition in a batch fileTheta
This question has become popular (viewed 1000 times) and there are not much upvotes to the question and answers. It makes me guess that visitors are coming to this page for something else and not finding it here. In other words, I guess this page is showing up in search results of some keywords irrelevant to this question. I wonder what that something else (or keywords irrelevant to this question) is and how can I change the title of this question so that the visitor's (who are expecting something else) time is saved.Theta
C
29

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
Captivate answered 16/6, 2010 at 5:39 Comment(10)
Thank you v much @paxdiablo! Can you please help me modify this so that I can only see a message box poping when the server gets up? The command for showing message box is msg "%username%" Link is up and this command works for me on Windows 7.Theta
That's a lot of work you do instead of just checking %ERRORLEVEL%!Reactionary
That's a good point, @Gabe, I've incorporated that into the script.Captivate
For some reason I don't know, the solution with @Gabe's suggession is showing message every time. @paxdiablo's 2nd solution works after one initial status message.Theta
Sorry, Ismael, that was my fault (not Gabe's) putting in debugging code (set oldstate=x!state!). It should work without the x in there.Captivate
Note that the pseudo-variable %errorlevel% isn't reliable as you can easily set its value from the outside (overshadowing its usual meaning). You probably want to use if errorlevel 1 instead of if !errorlevel!==0. And I shouldn't need to point this out, but parsing language-dependent strings is always an icky option for automation :-)Buber
It seems that ping gives an %errorlevel% of 0 when it gets a "Destination host unreachable" reply.Xanthus
@Captivate Could you explain each line please?Dharna
paxdiablo - Perhaps an idea to put the simpler solution first, with the trickier proposition below (even though some of us appreciate the solution when complex).Dynamite
Nice solutiion, except that the output gets translated on systems with another language. So checking for "Received" isn't possible. I guess checking if the three numbers are 1, 1 and 0 should also work.Acculturation
R
34

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.

Rubescent answered 14/8, 2010 at 22:18 Comment(1)
Use ping -4 parameter to force using IPv4. Great solution, thanks!Topless
C
29

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
Captivate answered 16/6, 2010 at 5:39 Comment(10)
Thank you v much @paxdiablo! Can you please help me modify this so that I can only see a message box poping when the server gets up? The command for showing message box is msg "%username%" Link is up and this command works for me on Windows 7.Theta
That's a lot of work you do instead of just checking %ERRORLEVEL%!Reactionary
That's a good point, @Gabe, I've incorporated that into the script.Captivate
For some reason I don't know, the solution with @Gabe's suggession is showing message every time. @paxdiablo's 2nd solution works after one initial status message.Theta
Sorry, Ismael, that was my fault (not Gabe's) putting in debugging code (set oldstate=x!state!). It should work without the x in there.Captivate
Note that the pseudo-variable %errorlevel% isn't reliable as you can easily set its value from the outside (overshadowing its usual meaning). You probably want to use if errorlevel 1 instead of if !errorlevel!==0. And I shouldn't need to point this out, but parsing language-dependent strings is always an icky option for automation :-)Buber
It seems that ping gives an %errorlevel% of 0 when it gets a "Destination host unreachable" reply.Xanthus
@Captivate Could you explain each line please?Dharna
paxdiablo - Perhaps an idea to put the simpler solution first, with the trickier proposition below (even though some of us appreciate the solution when complex).Dynamite
Nice solutiion, except that the output gets translated on systems with another language. So checking for "Received" isn't possible. I guess checking if the three numbers are 1, 1 and 0 should also work.Acculturation
K
9

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

Kindergartner answered 4/10, 2016 at 10:40 Comment(0)
P
2

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.

Parke answered 27/5, 2016 at 15:38 Comment(0)
J
2

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

Junkojunkyard answered 20/11, 2016 at 8:56 Comment(1)
This is simpler than many others and works for me. Except I changed find "Reply" to find "time=", because sometimes it would find Reply from X.X.X.X: Destination host unreachable. and count that as a success, when I would want it to be a failure.Maugre
M
1

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

Maura answered 17/8, 2022 at 21:25 Comment(0)
R
0

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

Redbreast answered 16/6, 2010 at 5:41 Comment(2)
We programmers can read and understand code faster than English language ;). Just joking.Theta
The OP probably wants to set the batch script running and then do other things on the machine, only to be alerted on a state change. Not sit and watch each ping reply result.Dynamite
A
0

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

)
Allometry answered 1/7, 2014 at 5:36 Comment(0)
C
0

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
Combat answered 14/5, 2017 at 18:15 Comment(0)
A
0

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.

Abiding answered 26/4, 2021 at 13:16 Comment(0)
A
0

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)
)
Anticathode answered 9/10, 2021 at 19:25 Comment(0)
R
-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.

Runnerup answered 16/10, 2014 at 22:57 Comment(1)
There is a "add comment" link (blue, all lower case, close to the line that separates the postings) below each answer, and the question. Please copy and paste your comments above into comments according to which respective question/answer they apply to. -1Dynamite
S
-2
#!/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
Sherrod answered 7/2, 2018 at 17:35 Comment(1)
The question is about windows batch files not bashLepus

© 2022 - 2024 — McMap. All rights reserved.