Link to home
Start Free TrialLog in
Avatar of makila
makila

asked on

Batch file to ping list of computers

How do I create a batch file that will read a csv or txt file as input to ping a list of computers and then output a file of the computers that did not reply? I will not be pinging IP addresses; I will be pinging computer names. I've been using this as a batch script but it takes forever and then I have to hunt for all the bad computer names line by line.

@ECHO OFF                  
ping      ORC11116413      -w      1000      >      ping.txt
ping      ORD11102296      -w      1000      >>      ping.txt

Thanks in advance!
-Makila
Avatar of Lee W, MVP
Lee W, MVP
Flag of United States of America image

Make the list of computer names, one per line and save it in a text file.  In the example below, I assume the text file is named "names.txt".  Then run this command:

for /f "tokens=1" %a in (names.txt) DO @ping -n 1 -w 100 %a ^| find /i "request" > ping.log

The above command is for running in a command prompt.  If you want to include this in a batch file, use %%a instead of %a

Actually, you probably want to replace the ">" quoted in my example to a ">>" as well.
Avatar of makila
makila

ASKER

I just tried that as a batch file and it gave me this error message:

"The process cannot access the file because it is being used by another process."

I put the batch file (ping.bat) and the input file (names.txt) in the C: directory and ran it from the command prompt window.
DON'T USE PING.BAT - PING is the EXE you need to use.  Windows checks the current directory for the command first - .bat, .exe, .com, etc - if found, it tries to use that one.  So it never gets a chance to run correctly.

rename ping.bat to something like "pinglist.bat"

If you want to get fancy, you could say "pinglist names.txt" then in the script, change the for line to the following:

for /f "tokens=1" %a in (%1) DO @ping -n 1 -w 100 %a ^| find /i "request" >> ping.log
Avatar of makila

ASKER

Ah ha! That worked. The ping.log has a bunch of lines of this error (Bad parameter |.) in between all the bad computer names. How do I get rid of those?
ASKER CERTIFIED SOLUTION
Avatar of Lee W, MVP
Lee W, MVP
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Here, I went a little nuts - see if you like this:

@echo off
If /i "%0" == "ping" Then Goto NameError
If /i "%0" == "if" Then Goto NameError
If /i "%0" == "for" Then Goto NameError
If /i "%0" == "find" Then Goto NameError
If /i "%0" == "type" Then Goto NameError
If /i "%0" == "echo" Then Goto NameError
If /i "%0" == "set" Then Goto NameError
if "%1" == "" Goto Usage
if /i "%1" == "showresults" Goto Usage
if /i "%1" == "alive" Goto Usage
If /i "%1" == "dead" goto usage
Set systemlist=%1
if /i "%2" == "alive" Set Criteria="Reply"
if /i "%3" == "alive" Set Criteria="Reply"
if /i "%4" == "alive" Set Criteria="Reply"
if /i "%2" == "dead" Set Criteria="Request"
if /i "%3" == "dead" Set Criteria="Request"
if /i "%4" == "dead" Set Criteria="Request"
if "%2" == "" SET LogFile=%0.log
if /i "%2" == "showresults" SET LogFile=%0.log
if /i "%2" == "alive" SET LogFile=%0.log
if /i "%2" == "dead" SET LogFile=%0.log
if exist ping.log del ping.log
for /f "tokens=1" %%a in (names.txt) DO @ping -n 1 -w 100 %%a | find /i "%criteria%" >> ping.log
if /i "%4" == "showresults" Type %logfile%
if /i "%3" == "showresults" Type %logfile%
if /i "%2" == "showresults" Type %logfile%
Goto End
:usage
Echo %0 SystemList.txt [logfile.log] [showresults] [alive^|dead]
echo.
echo      Where SystemList.txt is a text file with system names or IPs, one per line.
Echo        And logfile.log is the name of the log file to record the output to.
Echo            Default log file is %0.log
Echo.
Echo        showresults tells the script to display the log file upon script completion.
Echo.
Echo        alive tells the script to output all systems that respond to the ping request.
Echo        dead tells the script to output only the systems that do not respond to the
Echo                ping request.
Goto End
:NameError
Echo The name of this script cannot be "PING" as the "PING" command
Echo is an integral part of the script.  It cannot be named "IF", "FOR",
Echo "SET", "ECHO", "TYPE", or "FIND" either.
:end
Avatar of makila

ASKER

Wow! It didn't work but thanks for trying :) Removing the ^ did the trick for the error message in the log. Thanks so much for your help. I will continue to play around with the nutso script!
Avatar of makila

ASKER

Forgot to mention. This is how I ran it and what the error was from the nutso script:

C:\>pinglist2.bat names.txt ping2.log showresults dead
File not found - REQUEST
The system cannot find the file specified.
Try this one - I think I debugged it:

@echo off
If /i "%0" == "ping" Then Goto NameError
If /i "%0" == "if" Then Goto NameError
If /i "%0" == "for" Then Goto NameError
If /i "%0" == "find" Then Goto NameError
If /i "%0" == "type" Then Goto NameError
If /i "%0" == "echo" Then Goto NameError
If /i "%0" == "set" Then Goto NameError
if "%1" == "" Goto Usage
if /i "%1" == "showresults" Goto Usage
if /i "%1" == "alive" Goto Usage
If /i "%1" == "dead" goto usage
Set systemlist=%1
if /i "%2" == "alive" Set Criteria="Reply"
if /i "%3" == "alive" Set Criteria="Reply"
if /i "%4" == "alive" Set Criteria="Reply"
if /i "%2" == "dead" Set Criteria="Request"
if /i "%3" == "dead" Set Criteria="Request"
if /i "%4" == "dead" Set Criteria="Request"
If "%criteria%" == "" Then Set Criteria="Request"
if "%2" == "" SET LogFile=%0.log
if /i "%2" == "showresults" SET LogFile=%0.log
if /i "%2" == "alive" SET LogFile=%0.log
if /i "%2" == "dead" SET LogFile=%0.log
if exist %logfile% del %logfile%
for /f "tokens=1" %%a in (names.txt) DO @ping -n 1 -w 100 %%a | find /i %criteria% >> %logfile%
if /i "%4" == "showresults" Type %logfile%
if /i "%3" == "showresults" Type %logfile%
if /i "%2" == "showresults" Type %logfile%
Goto End
:usage
Echo.
Echo %0 SystemList.txt [logfile.log] [showresults] [alive^|dead]
echo.
echo      Where SystemList.txt is a text file with system names or IPs, one per line.
Echo        And logfile.log is the name of the log file to record the output to.
Echo            Default log file is %0.log
Echo.
Echo        showresults tells the script to display the log file upon script completion.
Echo.
Echo.
Echo       alive tells the script to output all systems that respond to the ping request.
Echo       dead tells the script to output only the systems that do not respond to the
Echo              ping request.  dead is the default setting.
Goto End
:NameError
Echo The name of this script cannot be "PING" as the "PING" command
Echo is an integral part of the script.  It cannot be named "IF", "FOR",
Echo "SET", "ECHO", "TYPE", or "FIND" either.
:end
Avatar of makila

ASKER

That one works better. The only problem is when I try to use the showresults parameter. It gives this error:

The syntax of the command is incorrect.

Thanks so much for all the help!
Hmmm... without providing me the text file, how exactly are you running the file?
New revision - don't think it will solve your problem, but try it anyway:



@echo off
REM PINGLIST.CMD - REVISION 3
If /i "%0" == "ping" Then Goto NameError
If /i "%0" == "if" Then Goto NameError
If /i "%0" == "for" Then Goto NameError
If /i "%0" == "find" Then Goto NameError
If /i "%0" == "type" Then Goto NameError
If /i "%0" == "echo" Then Goto NameError
If /i "%0" == "set" Then Goto NameError
if "%1" == "" Goto Usage
if /i "%1" == "showresults" Goto Usage
if /i "%1" == "alive" Goto Usage
If /i "%1" == "dead" goto usage
Set systemlist=%1
if /i "%2" == "alive" Set Criteria="Reply"
if /i "%3" == "alive" Set Criteria="Reply"
if /i "%4" == "alive" Set Criteria="Reply"
if /i "%2" == "dead" Set Criteria="Request"
if /i "%3" == "dead" Set Criteria="Request"
if /i "%4" == "dead" Set Criteria="Request"
If "%criteria%" == "" Then Set Criteria="Request"
if "%2" == "" SET LogFile=%0.log
if /i "%2" == "showresults" SET LogFile=%0.log
if /i "%2" == "alive" SET LogFile=%0.log
if /i "%2" == "dead" SET LogFile=%0.log
if exist %logfile% del %logfile%
for /f "tokens=1" %%a in (%systemlist%) DO @ping -n 1 -w 100 %%a | find /i %criteria% >> %logfile%
if /i "%4" == "showresults" Type %logfile%
if /i "%3" == "showresults" Type %logfile%
if /i "%2" == "showresults" Type %logfile%
Goto End
:usage
Echo.
Echo %0 SystemList.txt [logfile.log] [showresults] [alive^|dead]
echo.
echo      Where SystemList.txt is a text file with system names or IPs, one per line.
Echo        And logfile.log is the name of the log file to record the output to.
Echo            Default log file is %0.log
Echo.
Echo        showresults tells the script to display the log file upon script completion.
Echo.
Echo.
Echo       alive tells the script to output all systems that respond to the ping request.
Echo       dead tells the script to output only the systems that do not respond to the
Echo              ping request.  dead is the default setting.
Goto End
:NameError
Echo The name of this script cannot be "PING" as the "PING" command
Echo is an integral part of the script.  It cannot be named "IF", "FOR",
Echo "SET", "ECHO", "TYPE", or "FIND" either.
:end
REM Cleanup
Set Criteria=
Set Logfile=
Set SystemList=
Avatar of makila

ASKER

I ran it all these ways in the command prompt window and they didn't work:

pinglist2.bat names.txt ping2.log showresults
pinglist2.bat names.txt ping2.log showresults alive
pinglist2.bat names.txt ping2.log showresults dead
pinglist2.bat names.txt showresults
pinglist2.bat names.txt showresults alive
pinglist2.bat names.txt showresults dead

But if I leave the showresults out, it works fine. The names.txt is just a file with one computer name per line like:
computer1
computer2
computer3
I'll try it myself later or tomorrow - have to run tonight.  (One of these days I'm going to gather all my scripts and post them on the web.  So I DO want to perfect it at some point).
Despite Leew getting the well earned points, here's just another script that you can run, it gives a slightly, more user-friendly output:

:====8<-----[ FileName.cmd ]-----
@ECHO OFF
TITLE Network Check

REM -----------------------------------
REM

SET MachineList=names.txt
SET ResultsFile=results.txt

REM
REM -----------------------------------

CLS
ECHO.
IF NOT EXIST "%MachineList%" (
  ECHO Cannot locate Machine List: %MachineList%
  PAUSE>NUL
  GOTO :EOF
)

ECHO Processing all machine names in %MachineList% . . .
ECHO.

FOR /f "tokens=*" %%M in (%MachineList%) do CALL :CHECK "%%M"

GOTO :EOF

:CHECK
SET Machine=%~1
SET Machine=%Machine: =%

PING -w 1000 %Machine%>NUL
IF %ERRORLEVEL% NEQ 0 ECHO %Machine% did not respond at %Time%>>%ResultsFile%

EXIT /B

:EOF
:====8<-----[ FileName.cmd ]-----

HTH
[r.D]
Avatar of makila

ASKER

That worked beautifully! Thank you!
DrWarezz -

I thought I had too many If statements... you know any good tutorials on errorlevels?  
Glad it helped, makila.

Hey Leew,
erm.. The best 'tutorial' that covers Errorlevels that I've come across, and learnt just about everything I know about them from, is: <at command line> type IF /?

It covers Errorlevels somewhere down there.

But there's really not too much to them. Here's the jist of them:

All programs return a number %ERRORLEVEL% that represents how the program performed. Typically, 0 = successful, -1 = failed. Obviously though, it differs with programs, and certain errorlevels mean different things.. typically.. Then, it's just a case of use 'NEQ', 'EQU', 'GEQ', etc, operators to process the errorlevels.

Here's a rather important note, that I *think* is covered in the 'IF /?' output:

IF ERRORLEVEL 0 ECHO Errorlevel is 0

(for example)

Most people use that command, and believe that it will ECHO "Errorlevel is 0" if the errorlevel *is* 0. However, it doesn't, when you use that syntax, it will perform the task (in this case, ECHO Errorlevel is 0) if the %ERRORLEVEL% is Greater than, or equal to 0. So, it will do that operation even if the ERRORLEVEL is 999. So, just be careful with that one, and you'll figure the rest  ^_^

HTH
[r.D]
The issue I always run into with errorlevel is when I run pipes. Sometimes it will detect the errorlevel of the wrong pipe. For some reason if %errorlevel%==0 seems to work better than if errorlevel 0.

-Justin
DrWarezz:your script is awesome! What code would I need to modify for the results to show me the computers that were up instead of the ones that are down?

Thanks!