I have a script to continuously ping a set of machines (stored in SiteName.txt) and once a machine comes online, a counter increments, and the machine is removed from the list so it doesn't ping again (I just need to know if a machine has been online, not if it's on right now).
The issue I have is I've noticed there are a few phantom pings coming up with the IP address of the site they were built at (and that IP hasn't already been taken over by another machine) so I get false positives.
My current code is:
#echo off & setlocal EnableDelayedExpansion
TITLE %~n0
set /a counteron=0
for /F %%a in (%~n0.txt) do set "NVC=!NVC! %%a"
:ping
ping -n 61 127.0.0.1>nul
for %%i in (%NVC%) do (
ping %%i -n 1 | find "TTL=" >nul
if !errorlevel! GEQ 1 (
echo %%i is offline.
) else (
set /a counteron+=1
echo %%i is online
set "NVC=!NVC: %%i=!"
)
)
echo.
cls
echo. %counteron% machines are online.
if defined NVC goto :ping
cls
echo All machines in %~n0 are online.
pause
Is it possible to do the same thing, but if the IP's first 3 octets match a specific set (10.79.208.xxx), then it still comes up as offline?
Thanks in advance
Perhaps
ping %%i -n 1 | find "TTL=" |findstr /b /l /v /c:"Reply from 10.79.208." >nul
which should set errorlevel to zero only if both TTL= is found AND a line beginning (/b) with the /l literal string /c: "Reply from 10.79.208." is /v not found
which I believe is your quest...
Perhaps this slight alteration to your script is what you're after.
#echo off & setlocal enabledelayedexpansion
set nvc=192.168.1.1
for %%i in (%NVC%) do (
ping %%i -n 1 | find "TTL=" >nul
if !errorlevel! GEQ 1 (
echo %%i is offline.
) else (
for /f "tokens=1,2,3 delims=." %%j in ("%%i") do (
set octets=%%j.%%k.%%l
if "!octets!"=="10.79.208" (
echo %%i is false positive
) else (
set /a counteron+=1
echo %%i is online
set "NVC=!NVC: %%i=!"
)
)
)
)
Related
The code runs a very simple process of pinging multiple addresses endlessy and outputting the results to a log file until manually stopped.
#echo off
title ping_logger
set d1=%date:~4%
set d2=%d1:/=-%
set t1=%time::=.%
set t2=%t1: =%
set host=X.X.X.1;X.X.X.162
set hostname=%host:;=+%
set pinghostname=%host:;= and %
set logfile=Log_%hostname%_%ComputerName%_%d2%_%t2%.csv
setlocal enableextensions ENABLEDELAYEDEXPANSION
set counter=0
for %%A IN (%host%) DO (
set /a counter+=1
)
endlocal && set counter=%counter%
echo Target Host(s) = %host%>%logfile%
echo Pinging %pinghostname% with 32 bytes of data: >>%logfile%
timeout %counter% >NUL
:Ping
FOR %%A IN (%host%) DO (
for /F "tokens=* skip=2" %%A in ('ping %%A -n 1 ') do (
echo %date:~4%, %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A>>%logfile%
echo %date% %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A
)
)
IF (%counter% LSS 2) timeout 1 >NUL
GOTO Ping
The output is capturing too much into the log file. I'm looking to only get the first line from each response such as the highlighted lines
:DoPing
FOR %%A IN (%host%) DO (
set "pung="
for /F "tokens=* skip=2" %%A in ('ping %%A -n 1 ') do if not defined pung (
echo %date:~4%, %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A>>%logfile%
echo %date% %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A
set "pung=Y"
)
)
IF (%counter% LSS 2) timeout 1 >NUL
GOTO DoPing
(I'm allergic to using keywords/executable names as labels)
Simply set a flag value pung to nothing so that it is undefined when the pings start. On reporting the first line, set pung to non-empty, so it is then defined and the remining report lines are suppressed.
Next loop of %%A clears pung before issuing the ping for the next host...
Another way:
:DoPing
FOR %%A IN (%host%) DO (
for /F "tokens=1* skip=2" %%A in ('ping %%A -n 1 ') do if "%%A" == "Reply" (
echo %date:~4%, %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A %%B>>%logfile%
echo %date% %time:~0,2%:%time:~3,2%:%time:~6,2%, %%A %%B
)
)
IF (%counter% LSS 2) timeout 1 >NUL
GOTO DoPing
This time, see whether the first token is the string Reply and only write the report if this is so.
I'm stuck on this one, I've managed to create a batch file that imports list of IPs & hostnames but when I test for success or failure, I'd like to output how long it took. I don't know how to capture this and include it in the output. I'm trying to hide the default ping.exe output. Here's my code
#echo off
for /F "tokens=1,2 delims= " %%A in (computers.txt) do (
rem ping -n 1 %%A | findstr /i "TTL=" | find "Reply" > nul
if %errorlevel% == 0 (
echo %%B %%A successful ping in ?? Seconds
echo %%B %%A successful ping [%date%, %time%] >> log.txt
)
)
Pause
I've figured it out:
#echo off
setlocal enableDelayedExpansion
for /F "tokens=1,2 delims= " %%A in (computers.txt) do (
for /f "tokens=7 delims== " %%G in ('ping -n 1 %%A') do (
ping -n 1 %%A >nul
if errorlevel 1 (
echo %%B %%A unsuccessful ping
echo %%B %%A unsuccessful ping [!date!, !time!] >> log.txt
) else if "%%~G" NEQ "of" if "%%~G" NEQ "0" (
set ms=%%~G
set ms=!ms:ms=!
for /f %%Z in ('powershell !ms!/1000') do set second=%%~Z
echo %%B %%A successful ping in !second! seconds
echo %%B %%A successful ping [!date!, !time!] >> log.txt
)
)
)
Pause
Using FOR /F, it is possible to process command output.
As you may see, I have 2 ping -n 1 %%A. It is because FOR /F doesn't capture the ERRORLEVEL generated by the processing command. The first command gets the output, the second gets ERRORLEVEL.
if "%%~G" NEQ "of" if "%%~G" NEQ "0" filters out the unneeded results.
The powershell command converts milliseconds to second(batch file does not support decimal numbers)
I/O example
I don't have any other computers on my network, therefore I tested it with URLs.
Input -> Output
www.google.com A A www.google.com successful ping in 0.002 seconds
www.yahoo.com B B www.yahoo.com successful ping in 0.032 seconds
a.a.a C C a.a.a unsuccessful ping
I'm trying to write a script for work that tells me which machines on a network are online and which are offline.
Currently I have it showing me online/offline status, taking the PC names from a text file as input into a set variable.
The code I have so far is:
#echo off
setlocal EnableDelayedExpansion
for /F "tokens=*" %%a in (VC.txt) do call :append %%a
:ping
for %%i in (%VC) do (
ping %%1 -n 1 >nul
call :test %%i
)
echo.
goto :ping
:test
IF %ERRORLEVEL% EQU 0 (
echo Pinging %1
) else (
echo Off %1
)
goto :eof
:append
if defined VC (
set VC=%VC% %1
) else (
set VC=%1
)
What I want to happen is once a machine comes online, to remove it from the list. Basically just only show the list of the offline machines.
Is this possible without wiping the whole set and creating it fresh?
This mod do what you want:
:test
IF %ERRORLEVEL% EQU 0 (
echo Pinging %1
REM Remove this machine from the list
set "VC=!VC: %1=!"
) else (
echo Off %1
)
goto :eof
However, you have a couple small errors in your code. This is the fixed section:
:ping
for %%i in (%VC%) do (
ping %%i -n 1 >nul
call :test %%i
)
echo.
goto :ping
A couple points unrelated to your problem. If the machine names are single words with no spaces, then the "tokens=*" part in the for command is not needed. Also, all those call's and subroutines just complicate the code. This is the way I would do this:
#echo off
setlocal EnableDelayedExpansion
set "VC="
for /F %%a in (VC.txt) do set "VC=!VC! %%a"
:ping
for %%i in (%VC%) do (
ping %%i -n 1 >nul
IF !ERRORLEVEL! EQU 0 (
echo Pinging %%i
REM Remove this machine from the list
set "VC=!VC: %%i=!"
) else (
echo Off %%i
)
)
echo/
if defined VC goto :ping
echo All machines are on line
I'm trying to create a batch file where it would detect ping anomalies. I want it to ping to an IP infinitely (-t) until I close it where it would write down whenever ms > 100 ms and the time stamp as well. I'm thinking somewhere along the lines of sub string variables but I don't know how to wrap my head around it.
:Loop
time /t >> textfile.txt
ping -n 1 127.0.0.1 | findstr /c:"Minimum" >> textfile.txt
timeout /t 5
Goto Loop
Or perhaps this suits your needs
ping /t > textfile.txt
or
:loop
wmic /append:"textfile.txt" path win32_pingstatus where "address='127.0.0.1' and responsetime > 100" get responsetime,timestamprecord
goto loop
I've been looking for an answer to this same question for while. bgalea's answer gave me the pieces I needed to write my own. Here's what I came up with:
:: usage: badpings.bat [ip adress | hostname] [ping time threshhold]
#echo off
if "%1"=="" (
set pingdest=yahoo.com
) else (
set pingdest=%1
)
if "%2"=="" (
set /a limit=100
) else (
set /a limit=%2
)
echo Pinging %pingdest%.
echo Logging replies over %limit%ms.
echo Press Ctrl+C to end.
:Loop
for /f "usebackq tokens=1-6" %%a in (`ping -n 1 %pingdest% ^| findstr "Request Reply request"`) do (
set var=%%a %%b %%c %%d %%e %%f
set pingtimestr=%%e
)
if "%pingtimestr%"=="find" (
echo Ping request could not find host %pingdest%. Please check the name and try again.
goto End
)
if "%pingtimestr%"=="host" (
set /a pingtime=%limit%+1
)
if "%pingtimestr:~0,4%"=="time" (
set /a pingtime=%pingtimestr:~5,-2%
)
if %pingtime% GTR %limit% (
echo [%time%] %var%>>badpings.log
echo [%time%] %var%)
timeout /t 1 /nobreak >nul
Goto Loop
:End
It works on Windows 10. I haven't tested it on other OS versions.
So I have to use batch only for this. Basically, the server HOSTNAMES are all listed in a txt file. I used the following code to ping all the servers and display their results in a txtfile.
For /f %%i in (testservers.txt) do ping -n 1 %%i >>pingtest.txt
The above pinged all the servers. Now, I want to output the IP addresses and the HOST Names in a separate file. How can I do this?
I know that I can run a for loop searching for words like "TTL" and then look for the 3rd token (for the IP) and words like "PINGING" for the second token(HOSTNAME). But I am having errors and cant display it properly. The reason why I want to output IPs and Hostnames in a different file is to make a list of the DOWN and UP servers.
Help will be appreciated. :)
EDIT: Just so it isn't confusing, wanted to let you guys know there are 3 different files, testservers.txt has the HOSTNAMES in it, pingtest.txt has ping results, and result.txt will have the IPs along with Hostnames with their current status as DOWN or UP.
Well, it's unfortunate that you didn't post your own code too, so that it could be corrected.
Anyway, here's my own solution to this:
#echo off
setlocal enabledelayedexpansion
set OUTPUT_FILE=result.txt
>nul copy nul %OUTPUT_FILE%
for /f %%i in (testservers.txt) do (
set SERVER_ADDRESS=ADDRESS N/A
for /f "tokens=1,2,3" %%x in ('ping -n 1 %%i ^&^& echo SERVER_IS_UP') do (
if %%x==Pinging set SERVER_ADDRESS=%%y
if %%x==Reply set SERVER_ADDRESS=%%z
if %%x==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo %%i [!SERVER_ADDRESS::=!] is !SERVER_STATE! >>%OUTPUT_FILE%
)
The outer loop iterates through the hosts and the inner loop parses the ping output. The first two if statements handle the two possible cases of IP address resolution:
The host name is the host IP address.
The host IP address can be resolved from its name.
If the host IP address cannot be resolved, the address is set to "ADDRESS N/A".
Hope this helps.
Parsing pingtest.txt for each HOST name and result with batch is difficult because the name and result are on different lines.
It is much easier to test the result (the returned error code) of each PING command directly instead of redirecting to a file. It is also more efficient to enclose the entire construct in parens and redirect the final output just once.
>result.txt (
for /f %%i in (testservers.txt) do ping -n 1 %%i >nul && echo %%i UP||echo %%i DOWN
)
I worked on the code given earlier by Eitan-T and reworked to output to CSV file. Found the results in earlier code weren't always giving correct values as well so i've improved it.
testservers.txt
SOMESERVER
DUDSERVER
results.csv
HOSTNAME LONGNAME IPADDRESS STATE
SOMESERVER SOMESERVER.DOMAIN.SUF 10.1.1.1 UP
DUDSERVER UNRESOLVED UNRESOLVED DOWN
pingtest.bat
#echo off
setlocal enabledelayedexpansion
set OUTPUT_FILE=result.csv
>nul copy nul %OUTPUT_FILE%
echo HOSTNAME,LONGNAME,IPADDRESS,STATE >%OUTPUT_FILE%
for /f %%i in (testservers.txt) do (
set SERVER_ADDRESS_I=UNRESOLVED
set SERVER_ADDRESS_L=UNRESOLVED
for /f "tokens=1,2,3" %%x in ('ping -n 1 %%i ^&^& echo SERVER_IS_UP') do (
if %%x==Pinging set SERVER_ADDRESS_L=%%y
if %%x==Pinging set SERVER_ADDRESS_I=%%z
if %%x==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo %%i [!SERVER_ADDRESS_L::=!] !SERVER_ADDRESS_I::=! is !SERVER_STATE!
echo %%i,!SERVER_ADDRESS_L::=!,!SERVER_ADDRESS_I::=!,!SERVER_STATE! >>%OUTPUT_FILE%
)
the problem with ping is if the host is not alive often your local machine will return an answer that the pinged host is not available, thus the errorcode of ping will be 0 and your code will run in error because not recognizing the down state.
better do it this way
ping -n 4 %1 | findstr TTL
if %errorlevel%==0 (goto :eof) else (goto :error)
this way you look for a typical string ttl which is always in the well done ping result and check error on this findstr instead of irritating ping
overall this looks like this:
#echo off
SetLocal
set log=path/to/logfile.txt
set check=path/to/checkfile.txt
:start
echo. some echo date >>%log%
:check
for /f %%r in (%check%) do (call :ping %%r)
goto :eof
:ping
ping -n 4 %1 | findstr TTL
if %errorlevel%==0 (goto :eof) else (goto :error)
:error
echo. some errormessage to >>%log%
echo. some blat to mail?
:eof
echo. some good message to >>%log%
Try this
$servers = Get-Content test.txt
$reg=""
foreach ($server in $servers)
{
$reg=$reg+$server+"`t"+([System.Net.Dns]::GetHostAddresses($server) | foreach {echo $_.IPAddressToString})+"`n"
}
$reg >reg.csv
#echo off
set workdir={your working dir. for example - C:\work }
set iplist=%workdir%\IP-list.txt
setlocal enabledelayedexpansion
set OUTPUT_FILE=%workdir%\result.csv
>nul copy nul %OUTPUT_FILE%
echo HOSTNAME,LONGNAME,IPADDRESS,STATE >%OUTPUT_FILE%
for /f %%i in (%iplist%) do (
set SERVER_ADDRESS_I=UNRESOLVED
set SERVER_ADDRESS_L=UNRESOLVED
for /f "tokens=1,2,3" %%x in ('ping -a -n 1 %%i ^&^& echo SERVER_IS_UP') do (
if %%x==Pinging set SERVER_ADDRESS_L=%%y
if %%x==Pinging set SERVER_ADDRESS_I=%%z
if %%x==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo %%i [!SERVER_ADDRESS_L::=!] !SERVER_ADDRESS_I::=! is !SERVER_STATE!
echo %%i,!SERVER_ADDRESS_L::=!,!SERVER_ADDRESS_I::=!,!SERVER_STATE! >>%OUTPUT_FILE%
)
This worked great I just add the -a option to ping to resolve the
hostname. Thanks https://stackoverflow.com/users/4447323/wombat
#echo off
setlocal enabledelayedexpansion
set OUTPUT_FILE=result.csv
>nul copy nul %OUTPUT_FILE%
echo HOSTNAME,LONGNAME,IPADDRESS,STATE >%OUTPUT_FILE%
for /f %%i in (testservers.txt) do (
set SERVER_ADDRESS_I=UNRESOLVED
set SERVER_ADDRESS_L=UNRESOLVED
for /f "tokens=1,2,3" %%x in ('ping -n 1 -a %%i ^&^& echo SERVER_IS_UP') do (
if %%x==Pinging set SERVER_ADDRESS_L=%%y
if %%x==Pinging set SERVER_ADDRESS_I=%%z
if %%x==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo %%i [!SERVER_ADDRESS_L::=!] !SERVER_ADDRESS_I::=! is !SERVER_STATE!
echo %%i,!SERVER_ADDRESS_L::=!,!SERVER_ADDRESS_I::=!,!SERVER_STATE! >>%OUTPUT_FILE%
)
This works for spanish operation system.
Script accepts two parameters:
a file with the list of IP or domains
output file
script.bat listofurls.txt output.txt
#echo off
setlocal enabledelayedexpansion
set OUTPUT_FILE=%2
>nul copy nul %OUTPUT_FILE%
for /f %%i in (%1) do (
set SERVER_ADDRESS=No se pudo resolver el host
for /f "tokens=1,2,3,4,5" %%v in ('ping -a -n 1 %%i ^&^& echo SERVER_IS_UP')
do (
if %%v==Haciendo set SERVER_ADDRESS=%%z
if %%v==Respuesta set SERVER_ADDRESS=%%x
if %%v==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo %%i [!SERVER_ADDRESS::=!] is !SERVER_STATE! >>%OUTPUT_FILE%
echo %%i [!SERVER_ADDRESS::=!] is !SERVER_STATE!
)