Answered by:
Explain the Batch script to ping multiple computers

Question
-
Hello,
Please comment and explain each liner of the script.
@echo off
if exist d:\tools\computers.txt goto Label1
echo.
echo Cannot find d:\tools\computers.txt
echo.
Pause
goto :eof:Label1
echo PingTest executed on %date% at %time% > d:\tools\z.txt
echo ================================================= >> d:\tools\z.txt
for /f %%i in (d:\tools\computers.txt do call :Sub %%i
notepad d:\tools\z.txt
goto :eof:Sub
echo Testing %1
set state=alive
ping -n 1 %1 | find /i "bytes=" || set state=dead
echo %1 is %state% >> d:\tools\z.txtMonday, December 21, 2009 11:47 AM
Answers
-
@echo off
Don't echo these batch file commands to the screen. Using the @ sign means including the current line.
if exist d:\tools\computers.txt goto Label1
If there is a file called d:\tools\computers.txt then jump to the section of the batch file called :Label1
echo.
Type a dot to the screen.
echo Cannot find d:\tools\computers.txt
As the file called d:\tools\computers.txt was not found then type "Cannot find Etc." to the screen. This file must exist in the location specified. It presumably contains a list of machine names or IP addresses; one per line.
Pause
Put a prompt on the screen which says "Press any key to continue..." and then wait until a key is pressed.
goto :eof
Go to the end of the batch file (i.e. terminate)
:Label1
Now there is a subsection called Label
echo PingTest executed on %date% at %time% > d:\tools\z.txt
Type the words "PingTest executed on " along with the current date and time " but instead of typing them to the screen, pass them (using the > symbol) to a file called d:\tools\z.txt
for /f %%i in (d:\tools\computers.txt do call :Sub %%i
There's actually a bracket missing from this, so the correct line should read:
for /f %%i in (d:\tools\computers.txt) do call :Sub %%i
Loop through each line of the file d:\tools\computers.txt which presumably contains a list of machine names or IP addresses. Call a subroutine called :Sub passing it the line that's just been read. For example this file might look like:
193.1.1.1
193.1.1.2
193.1.1.200
notepad d:\tools\z.txt
The file d:\tools\z.txt is a log produced by the batch file. This line will launch NotePad with this file so you can view it.
goto :eof
Go to the end of the batch file (i.e. terminate)
:Sub
This is the subsection call Sub which gets called by the For loop.
echo Testing %1
Type to the screen the line that has been passed to this subsection. For example, "Testing 193.1.1.1"
set state=alive
Create a temporary value called "state" which is set to "alive"
ping -n 1 %1 | find /i "bytes=" || set state=dead
Call the PING executable. If you want to know more about this command then type PING /? from the command line. The output from this is then "piped" to the FIND executable which is set to ignore case (/i). Essentially it's looking for the PING command to be returning the text "bytes=" meaning that the IP address or machine name is responding to the ping. If the text is not found (so the find command failed) then the "state" value is changed from "alive" to "dead".
echo %1 is %state% >> d:\tools\z.txt
Type the IP address and the state value (dead or alive) to the file d:\tools\z.txt . The presence of the two > characters means append rather than overwrite.
There is some very clever batch file stuff in here, especially the use of the FOR command calling the subroutine and passing it a line at a time read from the text file, and then in the subroutine the use of the output piped from the PING command into the FIND command and then setting the state value if the find fails.
Very underrated things batch files.- Marked as answer by IamMred Sunday, January 17, 2010 8:32 AM
Monday, December 21, 2009 1:37 PM -
Change the line immediately after :Label1 to read ...
echo PingTest STARTED on %date% at %time% >> %lnm%
That is, add another greater than symbol, ">", after the %time% variable. This converts this line from creating a new file befor writing to appending to an existing file, if one exists.
BTW, a better way to post your question might be to cite this thread in a new question. That way it is not marked as answered, so more people are likely to review it.
Tom Lavedas- Marked as answer by Tom Lavedas Wednesday, February 16, 2011 7:01 PM
- Edited by Tom Lavedas Wednesday, February 16, 2011 7:02 PM to correct an embarassing typo
Wednesday, February 16, 2011 6:25 PM
All replies
-
@echo off
Don't echo these batch file commands to the screen. Using the @ sign means including the current line.
if exist d:\tools\computers.txt goto Label1
If there is a file called d:\tools\computers.txt then jump to the section of the batch file called :Label1
echo.
Type a dot to the screen.
echo Cannot find d:\tools\computers.txt
As the file called d:\tools\computers.txt was not found then type "Cannot find Etc." to the screen. This file must exist in the location specified. It presumably contains a list of machine names or IP addresses; one per line.
Pause
Put a prompt on the screen which says "Press any key to continue..." and then wait until a key is pressed.
goto :eof
Go to the end of the batch file (i.e. terminate)
:Label1
Now there is a subsection called Label
echo PingTest executed on %date% at %time% > d:\tools\z.txt
Type the words "PingTest executed on " along with the current date and time " but instead of typing them to the screen, pass them (using the > symbol) to a file called d:\tools\z.txt
for /f %%i in (d:\tools\computers.txt do call :Sub %%i
There's actually a bracket missing from this, so the correct line should read:
for /f %%i in (d:\tools\computers.txt) do call :Sub %%i
Loop through each line of the file d:\tools\computers.txt which presumably contains a list of machine names or IP addresses. Call a subroutine called :Sub passing it the line that's just been read. For example this file might look like:
193.1.1.1
193.1.1.2
193.1.1.200
notepad d:\tools\z.txt
The file d:\tools\z.txt is a log produced by the batch file. This line will launch NotePad with this file so you can view it.
goto :eof
Go to the end of the batch file (i.e. terminate)
:Sub
This is the subsection call Sub which gets called by the For loop.
echo Testing %1
Type to the screen the line that has been passed to this subsection. For example, "Testing 193.1.1.1"
set state=alive
Create a temporary value called "state" which is set to "alive"
ping -n 1 %1 | find /i "bytes=" || set state=dead
Call the PING executable. If you want to know more about this command then type PING /? from the command line. The output from this is then "piped" to the FIND executable which is set to ignore case (/i). Essentially it's looking for the PING command to be returning the text "bytes=" meaning that the IP address or machine name is responding to the ping. If the text is not found (so the find command failed) then the "state" value is changed from "alive" to "dead".
echo %1 is %state% >> d:\tools\z.txt
Type the IP address and the state value (dead or alive) to the file d:\tools\z.txt . The presence of the two > characters means append rather than overwrite.
There is some very clever batch file stuff in here, especially the use of the FOR command calling the subroutine and passing it a line at a time read from the text file, and then in the subroutine the use of the output piped from the PING command into the FIND command and then setting the state value if the find fails.
Very underrated things batch files.- Marked as answer by IamMred Sunday, January 17, 2010 8:32 AM
Monday, December 21, 2009 1:37 PM -
Thanks a ton for your quick turn around.
have 2 qq's
1. When i run this script i get the successful ping status only on the command prompt window.
What do I need to change if i want to get the failed oping status also?
2. Can you provide me any other simple batch file better than this.
Regards,
SufficeWednesday, December 23, 2009 4:59 AM -
1. Just add this as the last line:
echo %1 is %state%
It will type to the screen the current value the Sub loop is working on (%1) and the value of the parameter state.
2. Better than what? Better than this batch file at identifying if a load of computers are on?
Better than this one you were given as homework?!
No - there is nothing better than this batch file. It's the best batch file in the whole world. Other batch files bow down before it and remark themselves out of existence.....except possibily for this batch file (courtesy of Mark Minasi at Windows IT Pro) which beats it by virtue of being a game:
@echo off set guessesleft=16 set gamevalue=%random% echo I'm thinking of a number between 0 and 32767. echo %gamevalue% :looptop set /p latestguess=What's your guess (only %guessesleft% left)? set guessright=false set /a guessesleft=%guessesleft%-1 if /i %latestguess% equ %gamevalue% echo You got it! & set guessright=true if /i %latestguess% lss %gamevalue% echo Too small. if /i %latestguess% gtr %gamevalue% echo Too large. if /i %guessesleft% leq 0 goto byebye if NOT %guessright%==true goto looptop :byebye if NOT %guessright%==true echo Sorry ... you used up all your turns. The number was %gamevalue%.
Wednesday, December 23, 2009 10:16 AM -
thanks and merry christmas wishes belatedSunday, December 27, 2009 3:36 AM
-
I think this batch bows to that other batch too. :-)
echo I'm thinking of a number between 0 and 32767.
echo %gamevalue%
I'm thinking of a number between 0 and 32767.
16541
What's your guess (only 16 left)?16541
You got it!- Proposed as answer by titanyoda Tuesday, March 30, 2010 3:45 AM
Sunday, December 27, 2009 7:24 AM -
Actually, this script is TONS better, more modular and resilient -
The-Cat or whoever wrote the other script; well... it doesn't work. Not for Windows 7. It works for XP, for the most part.
Reason being is that Windows 7 and some other systems do not reply with "bytes=" on each successful line of the ping.
@echo off
set fnm=c:\scripts\computers.txt
set lnm=c:\scripts\pingme.txtif exist %fnm% goto Label1
echo.
echo Cannot find %fnm%
echo.
Pause
goto :eof:Label1
echo PingTest STARTED on %date% at %time% > %lnm%
echo ================================================= >> %lnm%
echo.
for /f %%i in (%fnm%) do call :Sub %%i
echo.
echo ================================================= >> %lnm%
echo PingTest ENDED on %date% at %time% >> %lnm%
echo ... now exiting
goto :eof:Sub
echo Testing %1
set state=alive
ping -n 1 %1
if errorlevel 1 set state=dead
echo %1 is %state% >> %lnm%[let me know what you think]
TIPS:
1) I always have 2 folders on c: drive - "scripts" and "tools" - where I have most scripts & ... umm... tools
2) I always use variables to make scripts more modular; i.e., set fnm=c:\scripts\computers.txt
3) I always name the "log/results" file the same as the BAT file, but with ".txt" for the suffix
4) I always have a "Time Started" and "Time Ended" in the log/results file
5) Using "errorlevel," in this case, produces more accurate results than testing for "bytes="
Cheers!Tuesday, March 30, 2010 3:53 AM -
Thanks. This script worked wondefully .Friday, July 23, 2010 6:58 AM
-
Hi Titanyoda,
I found the problem and corrected it. It is working now.
Monday, August 23, 2010 5:49 PM -
Hi,
How can i get the status for continuos period of 20mins,can you please give the batch for the same?
Wednesday, September 1, 2010 9:09 PM -
Actually, this script is TONS better, more modular and resilient -
The-Cat or whoever wrote the other script; well... it doesn't work. Not for Windows 7. It works for XP, for the most part.
Reason being is that Windows 7 and some other systems do not reply with "bytes=" on each successful line of the ping.
@echo off
set fnm=c:\scripts\computers.txt
set lnm=c:\scripts\pingme.txtif exist %fnm% goto Label1
echo.
echo Cannot find %fnm%
echo.
Pause
goto :eof:Label1
echo PingTest STARTED on %date% at %time% > %lnm%
echo ================================================= >> %lnm%
echo.
for /f %%i in (%fnm%) do call :Sub %%i
echo.
echo ================================================= >> %lnm%
echo PingTest ENDED on %date% at %time% >> %lnm%
echo ... now exiting
goto :eof:Sub
echo Testing %1
set state=alive
ping -n 1 %1
if errorlevel 1 set state=dead
echo %1 is %state% >> %lnm%[let me know what you think]
TIPS:
1) I always have 2 folders on c: drive - "scripts" and "tools" - where I have most scripts & ... umm... tools
2) I always use variables to make scripts more modular; i.e., set fnm=c:\scripts\computers.txt
3) I always name the "log/results" file the same as the BAT file, but with ".txt" for the suffix
4) I always have a "Time Started" and "Time Ended" in the log/results file
5) Using "errorlevel," in this case, produces more accurate results than testing for "bytes="
Cheers!Thanks for the script! Can you also advice how to keep all outputs/ping results in file pingme.txt without overwriting it.
I would like to schedule a task that will execute this script every 2 minutes to check if destination is reachable. But I am not sure, how to modify the script to append/save all ping results in file pingme.txt. Any feedback would be appriciated.
Thank you so much!
Vik
Wednesday, February 16, 2011 4:54 PM -
Thanks for the script! Can you also advice how to keep all outputs/ping results in file pingme.txt without overwriting it.
I would like to schedule a task that will execute this script every 2 minutes to check if destination is reachable. But I am not sure, how to modify the script to append/save all ping results in file pingme.txt. Any feedback would be appriciated.
Thank you so much!
Vik
Wednesday, February 16, 2011 4:55 PM -
Change the line immediately after :Label1 to read ...
echo PingTest STARTED on %date% at %time% >> %lnm%
That is, add another greater than symbol, ">", after the %time% variable. This converts this line from creating a new file befor writing to appending to an existing file, if one exists.
BTW, a better way to post your question might be to cite this thread in a new question. That way it is not marked as answered, so more people are likely to review it.
Tom Lavedas- Marked as answer by Tom Lavedas Wednesday, February 16, 2011 7:01 PM
- Edited by Tom Lavedas Wednesday, February 16, 2011 7:02 PM to correct an embarassing typo
Wednesday, February 16, 2011 6:25 PM -
Tom,
Got you. Thanks a lot. It worked like a charm ;).
Vik
Wednesday, February 16, 2011 6:37 PM -
Script works well when i execute it in a command prompt. But I want to schedule the command.
When i create a scheduled task under Windows2003 ( executable name is a .cmd) i get an error "Testing -n" in the command prompt.
What's wrong??
Help,
J
ICT specialistTuesday, March 1, 2011 9:22 AM -
great piece of scriptSunday, April 3, 2011 7:49 AM
-
Thanks for the script, i'm working on health check script, i would like to modify the script by adding uptime function to check uptime for 'alive' servers only and include it to the report, any idea how can i do this, i try to google arround but can't find anything similliar to it. Thanks.Monday, May 30, 2011 9:24 AM
-
Try using an internet search engine and putting in the query "How Can I Determine the Uptime for a Server", at which point it will possibly point you in the direction of this VBScript:
http://blogs.technet.com/b/heyscriptingguy/archive/2005/08/02/how-can-i-determine-the-uptime-for-a-server.aspx
Or you might be drawn to this PowerShell version:
http://technet.microsoft.com/en-us/magazine/2008.12.heyscriptingguy.aspx
If you wanted a pure batch file to do this then I reckon you're probably out of luck. You'd need a hybrid solution, perhaps using WMIC which is a command line WMI tool like this:
wmic /NODE:servername PATH "Win32_PerfFormattedData_PerfOS_System" GET "SystemUpTime" /VALUE
Tuesday, May 31, 2011 10:36 AM -
Try using an internet search engine and putting in the query "How Can I Determine the Uptime for a Server", at which point it will possibly point you in the direction of this VBScript:
http://blogs.technet.com/b/heyscriptingguy/archive/2005/08/02/how-can-i-determine-the-uptime-for-a-server.aspx
Or you might be drawn to this PowerShell version:
http://technet.microsoft.com/en-us/magazine/2008.12.heyscriptingguy.aspx
If you wanted a pure batch file to do this then I reckon you're probably out of luck. You'd need a hybrid solution, perhaps using WMIC which is a command line WMI tool like this:
wmic /NODE:servername PATH "Win32_PerfFormattedData_PerfOS_System" GET "SystemUpTime" /VALUE
Thanks for the advice, i'm really appriciate it, i'm thinking of using powershell as well, i have the batch script where i can pull the uptime info like below,@echo off
(for /f "tokens=* delims= " %%a in (c:\batch\Servers.txt) do (uptime.exe %%a /p:2)) >> c:\temp\results.txt
@echo "Result were directed to C:\temp\result.txt"
pauseI'm thinking how it possible to merge it to script provided by titanyoda earlier and make the output to 1 file only.
Tuesday, May 31, 2011 5:46 PM -
Just add the following to the end of that batch file then. It calls WMIC to get the SystemUpTime but you could use an EXE if you have one that does the same thing:
if %state%==alive wmic /NODE:%1 PATH "Win32_PerfFormattedData_PerfOS_System" GET "SystemUpTime" /VALUE | find "SystemUpTime" >>%lnm%
Tuesday, May 31, 2011 6:22 PM -
Thanks it work like a charm, i using 'uptime' tool instead wmic as the output is properly state the uptime;
Health check STARTED on 01/06/2011 at 2:40:30,54
=================================================
Server1a.wmservice.corpnet1.com is alive
\\Server1a.wmservice.corpnet1.com has been up for: 9 day(s), 4 hour(s), 5 minute(s), 56 second(s)
Server1b.wmservice.corpnet1.com is down/unreachable
Server1c.wmservice.corpnet1.com is alive
\\STVSAWN733.wmservice.corpnet1.com has been up for: 9 day(s), 1 hour(s), 32 minute(s), 18 second(s)
=================================================
Health check ENDED on 01/06/2011 at 2:40:50,15
Tuesday, May 31, 2011 6:43 PM -
Actually, this script is TONS better, more modular and resilient -
The-Cat or whoever wrote the other script; well... it doesn't work. Not for Windows 7. It works for XP, for the most part.
Reason being is that Windows 7 and some other systems do not reply with "bytes=" on each successful line of the ping.
@echo off
set fnm=c:\scripts\computers.txt
set lnm=c:\scripts\pingme.txtif exist %fnm% goto Label1
echo.
echo Cannot find %fnm%
echo.
Pause
goto :eof:Label1
echo PingTest STARTED on %date% at %time% > %lnm%
echo ================================================= >> %lnm%
echo.
for /f %%i in (%fnm%) do call :Sub %%i
echo.
echo ================================================= >> %lnm%
echo PingTest ENDED on %date% at %time% >> %lnm%
echo ... now exiting
goto :eof:Sub
echo Testing %1
set state=alive
ping -n 1 %1
if errorlevel 1 set state=dead
echo %1 is %state% >> %lnm%[let me know what you think]
TIPS:
1) I always have 2 folders on c: drive - "scripts" and "tools" - where I have most scripts & ... umm... tools
2) I always use variables to make scripts more modular; i.e., set fnm=c:\scripts\computers.txt
3) I always name the "log/results" file the same as the BAT file, but with ".txt" for the suffix
4) I always have a "Time Started" and "Time Ended" in the log/results file
5) Using "errorlevel," in this case, produces more accurate results than testing for "bytes="
Cheers!
How would you be able to record the IP's of each ping test with this script?It's cool that it tells you if it's working or dead, just would like the IP to be listed as well next to the computer being pinged. Thanks for all of your help! This saves me ages of time!
Sunday, January 22, 2012 2:20 AM -
Actually, this script is TONS better, more modular and resilient -
The-Cat or whoever wrote the other script; well... it doesn't work. Not for Windows 7. It works for XP, for the most part.
Reason being is that Windows 7 and some other systems do not reply with "bytes=" on each successful line of the ping.
@echo off
set fnm=c:\scripts\computers.txt
set lnm=c:\scripts\pingme.txtif exist %fnm% goto Label1
echo.
echo Cannot find %fnm%
echo.
Pause
goto :eof:Label1
echo PingTest STARTED on %date% at %time% > %lnm%
echo ================================================= >> %lnm%
echo.
for /f %%i in (%fnm%) do call :Sub %%i
echo.
echo ================================================= >> %lnm%
echo PingTest ENDED on %date% at %time% >> %lnm%
echo ... now exiting
goto :eof:Sub
echo Testing %1
set state=alive
ping -n 1 %1
if errorlevel 1 set state=dead
echo %1 is %state% >> %lnm%[let me know what you think]
TIPS:
1) I always have 2 folders on c: drive - "scripts" and "tools" - where I have most scripts & ... umm... tools
2) I always use variables to make scripts more modular; i.e., set fnm=c:\scripts\computers.txt
3) I always name the "log/results" file the same as the BAT file, but with ".txt" for the suffix
4) I always have a "Time Started" and "Time Ended" in the log/results file
5) Using "errorlevel," in this case, produces more accurate results than testing for "bytes="
Cheers!
How would you be able to record the IP's of each ping test with this script?It's cool that it tells you if it's working or dead, just would like the IP to be listed as well next to the computer being pinged. Thanks for all of your help! This saves me ages of time!
Perfect script! But I also would like to know how to modify this script to display the IP address of both "Alive" and "Dead" machine names. Has anyone come across the answer. Thanks again for the great script.- Proposed as answer by Luke Douglas Sunday, November 1, 2015 9:07 AM
- Unproposed as answer by Luke Douglas Sunday, November 1, 2015 9:07 AM
Tuesday, October 23, 2012 4:35 PM -
Asking a question at the end of a long, two year old thread is not the best approach to getting an answer. It is better to start a new thread that references or links back to the old one.
First, what is the IP number of a machine that is not pingable?
Second, the ping output can be accessed to get IP addresses, when they are present using a FOR statement, something like this ...
:Sub
echo Testing %1
set state=alive
ver | find " 6.">nul && set "option_IP4=-4"||set "option="
set "IPAddr=UNKNOWN"
for /f "tokens=2 delims=[]" %%a in (
'ping -n 1 %1 %option_IP4%|find "Pinging"') do set IPAddr=%%a
if errorlevel 1 set state=dead
echo Computer %1 at %IPAddr% is %state% >> %lnm%Note that this assumes you want the IPv4 address on systems that support IPv6. Otherwise remove the VER test line.
Tom Lavedas
Tuesday, October 23, 2012 5:57 PM -
Hi Tom I have done what you advised but it didnt work, can you assist further. It simply did not run at all
This is after replacing the script below;
:Sub
echo Testing %1
set state=alive
ver | find " 6.">nul && set "option_IP4=-4"||set "option="
set "IPAddr=UNKNOWN"
for /f "tokens=2 delims=[]" %%a in (
'ping -n 1 %1 %option_IP4%|find "Pinging"') do set IPAddr=%%a
if errorlevel 1 set state=dead
echo Computer %1 at %IPAddr% is %state% >> %lnm%Thank you.
Wednesday, August 27, 2014 6:20 AM -
Hi Tom I have done what you advised but it didnt work, can you assist further.
Two years ago Tom wrote this:
Asking a question at the end of a long, two year old thread is not the best approach to getting an answer. It is better to start a new thread that references or links back to the old one.
It is now five years after this thread was started. Please do as Tom recommends.
Wednesday, August 27, 2014 8:01 AM -
EPIC!Thursday, April 16, 2015 9:05 AM
-
I modified this script slightly as the original would not work on my Windows 7. The culprit was the code "| pinging" which I took out. My website list is in websites.txt and the resulting file is pingwebs.txt.
@echo off set fnm=c:\websites.txt set lnm=c:\pingwebs.txt if exist %fnm% goto Label1 echo. echo Cannot find %fnm% echo. Pause goto :eof :Label1 echo PingTest STARTED on %date% at %time% > %lnm% echo ================================================= >> %lnm% echo. for /f %%i in (%fnm%) do call :Sub %%i echo. echo ================================================= >> %lnm% echo PingTest ENDED on %date% at %time% >> %lnm% echo ... now exiting goto :eof :Sub echo Testing %1 set state=alive set "IPAddr=UNKNOWN" for /f "tokens=2 delims=[]" %%a in ('ping -n 1 %1') do set IPAddr=%%a if errorlevel 1 set state=dead echo [%IPAddr%] %1 is %state% >> %lnm%
The resulting file looks like this (only 2 displayed but mine had over 50 websites):
PingTest STARTED on Sun 11/01/2015 at 2:51:13.08
=================================================
[198.1.81.235] HeadlandAlabama.com is alive
[198.1.81.235] Webbering.com is alive
=================================================
PingTest ENDED on Sun 11/01/2015 at 2:52:15.48- Edited by Luke Douglas Sunday, November 1, 2015 9:26 AM
Sunday, November 1, 2015 9:12 AM -
Testing the ErrorLevel after running ping.exe does not return a reliable result. You can easily confirm this yourself. Assuming that your current internal IP address is 192.168.1.20, try this:
ping 192.168.1.21
echo %ErrorLevel%The ErrorLevel is 0, even when 192.168.1.21 does not respond! Use this code instead:
ping 192.168.1.21 | find /i "bytes="
echo %ErrorLevel%Sunday, November 1, 2015 4:23 PM