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

Command LineBatch FilePing

Command Line Problem Overview


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 https://stackoverflow.com/questions/774175/how-can-i-open-a-message-box-in-a-windows-batch-file/774253#774253

and can ping continuously by

ping <servername> -t

But how do I check if it responded or not?

Command Line Solutions


Solution 1 - Command Line

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.

Solution 2 - Command Line

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

Solution 3 - Command Line

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

Solution 4 - Command Line

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.

Solution 5 - Command Line

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

Solution 6 - Command Line

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

Solution 7 - Command Line

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

Solution 8 - Command Line

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

Solution 9 - Command Line

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.

Solution 10 - Command Line

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

Solution 11 - Command Line

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.

Solution 12 - Command Line

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIsmailSView Question on Stackoverflow
Solution 1 - Command LineLukaszView Answer on Stackoverflow
Solution 2 - Command LinepaxdiabloView Answer on Stackoverflow
Solution 3 - Command LineBigrogView Answer on Stackoverflow
Solution 4 - Command LineJan LauridsenView Answer on Stackoverflow
Solution 5 - Command LineJugglerView Answer on Stackoverflow
Solution 6 - Command LineRotsorView Answer on Stackoverflow
Solution 7 - Command Linedamian1baranView Answer on Stackoverflow
Solution 8 - Command LineDan WView Answer on Stackoverflow
Solution 9 - Command LineBurmeindView Answer on Stackoverflow
Solution 10 - Command Linesys7emView Answer on Stackoverflow
Solution 11 - Command LinePhil ReinemannView Answer on Stackoverflow
Solution 12 - Command LineTalView Answer on Stackoverflow