Batch - Ping on Multiple sites - windows

So I want to ping, 20 different sites 15 consecutive times with the same data size and take their Average RTT into a file. But I must also check the same IP for different sizes of ping data, from 8 to 2048 every time multiplied with 2 (8, 16, 32, 64 etc).
I tried to develop my own code and here is what I have so far.
#echo off
CLS
ping -n 1 %1|find "Reply" > nul
CLS
IF %ERRORLEVEL% == 0 ( FOR %%G IN (8,16,32,64,128,256,512,1024,2048) DO (echo Pinging with %%G byte of data... & ping -n 1 -l %%G %1|findstr /x "^.*Request.* ^.*Lost.* ^.*Average.*ms" >> results.txt)) ELSE (ECHO The Server %1 did not respond)
For easier reading:
#echo off
CLS
ping -n 1 %1
CLS
IF %ERRORLEVEL% == 0
(
FOR %%G IN (8,16,32,64,128,256,512,1024,2048) DO
(
echo Pinging with %%G byte of data... &
ping -n 15 -l %%G %1|findstr /x "^.*Request.* ^.*Lost.* ^.*Average.*ms" >> results.txt
)
ELSE
( ECHO "The Server did not respond" )
What I want to accomplish is, a batch file that, accepts 10 (or 15 if it is possible) parameters that are websites ping all of them with 8, 16, 32, ..., 2048 for 15 times each site and also if the server for any reason in some of my ping requests gives me a Request time out, I want to stop the loop for this parameter and continue with the next one but I want it to write to the file that "Request Time Out"
In my code, I am trying to check if the server responds on my ping requests, if I get a reply then begin my FOR loop.
Although, I can't check at any given time if the server still accepts my pings, this happens more often when I have packets of 2048 bytes. If the server give me a "NO" then I get a "Request time out".
So with some kind of code implementation I want to check if the command
ping -n 15 -l %%G %1|findstr /x "^.*Request.* ^.*Lost.* ^.*Average.*ms"
will print Request Time Out so I can stop the ping and move on the next parameter, so it won't bother pinging the same IP 15 times.
Also, with the above implementation I won't have to check at the start of the script if the server responds because it will do it inside the FOR loop.
I believe that the parameter switching is not that hard to implement, it's just a shift and some labels.
Thank you in advance for your time, I will be glad to give you more explanations on the commends below!

Related

Windows Command Line - Select Server Based upon Ping Latency

Ok basic premise here is that there are two servers with the same files.
I'm using Windows command line scripts and opening a network share to either of those hosts. I'd like to make the script "smart" so it works out the latency between the two servers and picks the lowest latency host to connect to.
I want to do something like (i know this code doesn't work, it's an example of my concept):
PING 192.168.0.1
SET HOST1=%ERRORLEVEL%
PING 192.168.0.2
SET HOST2=%ERRORLEVEL%
IF HOST1 GTR HOST2 GOTO HOST2CONNECT
:HOST1CONNECT
NET USE X: \\HOST1 (etc)
:HOST2CONNECT
NET USE X: \\HOST2 (etc)
Does that make any sense? I just can't seem to visualise a way of comparing the data from the two PING tests and i know that ERRORLEVEL in this situation is just a 1 or 0 based upon whether the ping is successful or not, so it's garbage as they'll both succeed. But i'm hoping you get the concept and can see what i'm missing.
Thanks in advance.
#echo off
setlocal enableextensions disabledelayedexpansion
rem Initialize variables
set "selected="
set "min=99999999"
set serverList= "bing.com" "duckduckgo.com" "google.es" "google.com"
echo - Testing -----------------------------
rem Enumerate the hosts to check
for %%a in ( %serverList% ) do (
rem Ping the host and retrieve the average roundtrip
for /f "tokens=6 delims== " %%r in ('
ping -n 1 "%%~a" ^| findstr /r /c:"^ .*ms$"
') do for /f "delims=ms" %%t in ("%%r") do (
echo "%%~a" : %%t ms
rem Determine if the current host has a lower rtt
rem if %%t geq min or min is already 0, then we have
rem a division by 0, else a lower rtt has been found
set /a "1/(min/(%%t+1))" && (
set "selected=%%~a"
set "min=%%t"
)
rem Of course this can be done with delayed expansion,
rem just a question of personal preferences
)
) 2>nul
echo(
echo - Selected ----------------------------
echo %selected% : %min%
MC ND posted his answer before I did so he should deserve the credits. Please do not mark this as the answer, that is not the intention of my post.
Because I had already made the effort of posting an answer as well and for sake of completeness, I feel that it doesn't hurt to post another approach to deal with the problem. The main difference is that I've chosen to use the average round-trip times of the ping command and provide a way to store the latency times and target host names in a group of variables that could be considered an array of structures.
Keep in mind that measuring round-trip latency with the ping command is not very accurate and the results can fluctuate tremendously. Referring to the following quote from Wikipedia:
Many software platforms provide a service called ping that can be used
to measure round-trip latency. Ping performs no packet processing; it
merely sends a response back when it receives a packet (i.e. performs
a no-op), thus it is a first rough way of measuring latency. Ping
cannot perform accurate measurements, principally because it uses the
ICMP protocol that is used only for diagnostic or control purposes,
and differs from real communication protocols such as TCP.
Furthermore, routers and ISP's might apply different traffic shaping
policies to different protocols.
#echo off
setlocal enabledelayedexpansion
set targets="192.168.0.1" "192.168.0.2"
for %%e in (%targets%) do (
call :GetAverageLatency %%e latency
if errorlevel 1 (
echo Unable to obtain latency from host: %%~e
exit /b
)
set /a count+=1
set "host[!count!].name=%%~e"
set "host[!count!].latency=!latency!"
if -!latency! gtr -!lowest! (
set lowest=!latency!
set index=!count!
)
)
echo;Mapping network drive to host: !host[%index%].name!
echo;
net use * "\\!host[%index%].name!"
set host
exit /b
:GetAverageLatency (__in hostName, __out *latency) {
for /f "skip=10 tokens=13 delims=m " %%e in ('ping "%~1"') do (
set "%2=%%e"
exit /b 0
)
exit /b 1
}
The set host command is obviously not necessary but it used to show the values stored in the host* variables.

Improving Batch File for loop with start subcommand

I've currently got a very simple script which pings 10 IPs:
#ECHO OFF
for /L %%i in (100, 1, 110) DO (
START /W /B cmd /c ping -n 1 192.168.0.%%i | find "time="
)
The output is as expected:
C:\Users\herpderp>test.bat
Reply from 192.168.0.101: bytes=32 time=294ms TTL=64
Reply from 192.168.0.104: bytes=32 time=1ms TTL=64
However, it is VERY slow and definitely happening sequentially. When I run this with a PowerShell Measure-Command I get these results:
PS C:\Users\derpherp> measure-command {start-process test.bat -Wait}
Days : 0
Hours : 0
Minutes : 0
Seconds : 23
Milliseconds : 107
Ticks : 231074173
TotalDays : 0.000267446959490741
TotalHours : 0.00641872702777778
TotalMinutes : 0.385123621666667
TotalSeconds : 23.1074173
TotalMilliseconds : 23107.4173
So we see it is taking ~23 seconds to execute.
Now, if I were on a Linux system and wanted to do this same thing, I can do the following:
#!/bin/bash
for ip in $(seq 100 110); do
ping -c 1 192.168.0.$ip | grep "bytes from" | cut -d" " -f4 | cut -d ":" -f1 &
done
The result is different in a variety of ways:
The results aren't always sequential, meaning it actually started the commands more asynchronously:
root#kali:~/vids/bash_scripting# ./test.sh
192.168.0.104
192.168.0.100
192.168.0.103
192.168.0.101
The time for it to display all of the positive results is typically less than a second and this scales to much larger sets of numbers.
So, my question, is this a limitation of batch scripting? I find it hard to believe that bash performs literally 100s of times better than Windows CMD interpreter for such a simple task?
If this is limited, does PowerShell offer a competitive way to create tasks? I've used Start-Job in a foreach loop but that seems to become unworkable for large numbers of tasks (ie Test-Connection on a /16 network)
Edit 1
#ECHO OFF
for /L %%i in (100, 1, 110) DO (
ping -n 1 192.168.0.%%i | find "time="
)
This outputs the current window and takes just as long as the initial variant
#ECHO OFF
for /L %%i in (100, 1, 110) DO (
START ping -n 1 192.168.0.%%i | find "time="
)
This outputs to unique windows per IP and takes just as long to complete.
Asynchronous isn't easy, but with jobs you can get close pretty easily with PowerShell.
This code should behave how it looks like your bash code does, returning the IP address of all hosts that respond without error:
$IPAddresses = 100..110 | ForEach-Object { "192.168.0.$_"; }
$JobList = $IPAddresses | ForEach-Object {
Test-Connection -ComputerName $_ -Count 1 -AsJob;
}
Receive-Job -Job $JobList -AutoRemoveJob -Wait | `
Where-Object { $_.StatusCode -eq 0 } | `
Select-Object -ExpandProperty Address;
The above completes for me against ~250 hosts in 3 seconds.
Test-Connection itself claims to use up to 32 simultaneous connections (configurable with -ThrottleLimit setting) but it sure seems like the -Delay option completely overrides that setting if you're targeting a wide range.
You may have issues with PowerShell v4 and earlier, as it may behave slightly differently. Test-Connection in particular seems to be idiosyncratic on different versions of Windows or PowerShell. At least, I always remember it throwing an error instead of returning an error status code in previous versions.
If you want more fine grain control over the ping than Test-Connection gives you -- for example, it defaults to a 1 second timeout so the minimum time you'll wait when any host is down is 1 second -- you'll probably have to revert to directly calling Get-WMIObject -Query "SELECT * FROM Win32_PingStatus WHERE Address = '$IP' AND TimeOut = 200" -AsJob.
Seems that I have found a pure batch-file solution. Basically, the script fires several ping commands simultaneously, which all write their result to individual log files; these files are monitored for write-access, because the files are write-locked as long as the respective ping processes are ongoing; as soon as write-access is granted, the first lines of the log files containing the IP addresses are copied into a summary log file. So here is the code -- see all the explanatory rem remarks:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Predefine IP addresses as an array:
for /L %%J in (0,1,5) do (
set "IP[%%J]=127.0.0.%%J"
)
rem // Ping IP addresses simultaneously, create individual log files:
for /F "tokens=2,* delims=[=]" %%J in ('set IP[') do (
start "" /B cmd /C ping -n 2 %%K ^| find "TTL=" ^> "%~dpn0_%%J.log"
)
rem // Deplete summary log file:
> "%~dpn0.log" rem/
rem /* Polling loop to check whether individual log files are accessible;
rem this works, because a pinging process is not yet finished, the
rem respective log file is still opened and therefore write-locked: */
:POLL
rem // Give processor some time:
> nul timeout /T 1 /NOBREAK
rem /* Loop through all available array elements; for every accomplished
rem pinging process, the related array element becomes deleted, so
rem finally, there should not be any more array elements defined: */
for /F "tokens=2 delims=[=]" %%J in ('2^> nul set IP[') do (
rem // Suppress error message in case log file is write-locked:
2> nul (
rem // Try to append nothing to the log file:
>> "%~dpn0_%%J.log" rem/ && (
rem /* Appending succeeded, hence log file is no longer locked
rem and the respective pinging process has been finished;
rem therefore read the first line containing the IP: */
set "FILE=" & set "IP="
< "%~dpn0_%%J.log" set /P IP=""
rem // Copy the read line to the summary log file:
if defined IP >> "%~dpn0.log" call echo(%%IP%%
rem // Undefine related array element:
set "IP[%%J]="
rem // Store log file path for later deletion:
set "FILE=%~dpn0_%%J.log"
)
rem // Delete individual log file finally:
if defined FILE call del "%%FILE%%"
)
)
rem // Jump to polling loop in case there are still array elements:
> nul 2>&1 set IP[ && goto :POLL
endlocal
exit /B
You have no need of start command. You turn off all it's features. Then you tell it to start a new process for CMD which is slow and unnecessary. So - ping -n 1 192.168.0.%%i |find "time=".
See my summary here of how to start programs - What do all commands in batch mean and do?.
You can use start to run ping in parallel, but you need to remove /w which means wait (but it's being ignored because) and /b which says don't run the command in a new spawned process but do it sequentially.
As you are still doing multiple process creation of Ping you can use WMIC to avoid that and test all computers in one process create.
wmic /node:#"c:\computerlist.txt" /append:"textfile.txt" path win32_pingstatus where "address='127.0.0.1' and responsetime > 100" get responsetime,timestamprecord.
So we've gone from 20 process creates to 1.
In programming we have to pay taxes of system overhead. Windows collect most tax at Process Creation and Window Creation. This is to allow other operations to take place without as much system overheads. An example is Windows keeps tables of processes that are running - uses resources to update when a process is created but allows quick lookup for other operations.

Including first reply ping result in output file

I've searched already and honestly, the responses I've found so far, I don't understand enough to modify my existing code. Would appreciate any help.
I have a list of hostnames in a file called devices.txt and was provided this:
:TOP
for /f %%j in (devices.txt) do call CS.CMD %%j
:End
I then run the cs.cmd script I was provided which pings against the hostnames in the devices.txt file. Output is provided in 2 response files: Device_offline.txt
Devices_online.txt
The response files currently only contain the hostnames. I would like to have the IP addresses as well (for the devices responding), and ideally as a single line of text per devices (that way I can separate in spreadsheet if needed)
Here is the current script:
echo off
:TOP
echo %1 - Processed Device
echo.
echo Seeing if system is on.
echo.
:test
ping %1 -n 2 > pingout.lis
find "bytes="<pingout.lis
if errorlevel 1 goto badping
:goodping
echo.
echo Checking status on %1
echo
echo %1 - Device is online
echo %1 >> Device_Online.txt
goto End
:badping
echo
echo %1 - No ping response...The Device is turned off.
echo %1 >> Device_Offline.txt
GOTO End
:End
Conversely, I also have a list of IPs that I would like to ping and have offline/online output files with the associated hostname... maybe that's as easy as inputting IP addresses in the device.txt file instead of hostnames?
Appreciate any guidance, thank you!

Batch ERRORLEVEL ping response

I'm trying to use a batch file to confirm a network connection using ping. I want to do batch run and then print if the ping was successful or not. The problem is that it always displays 'failure' when run as a batch. Here is the code:
#echo off
cls
ping racer | find "Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),"
if not errorlevel 1 set error=success
if errorlevel 1 set error=failure
cls
echo Result: %error%
pause
'racer' is the name of my computer. I'm having my computer ping itself so I can eliminate the variable of a poor connection. As I said before, the batch always results in failure. Oddly enough, the program works fine if I copy the code into the command prompt. Does anyone know why the program works fine in the command prompt but doesn't work as a batch?
Thanks
A more reliable ping error checking method:
#echo off
set "host=192.168.1.1"
ping -n 1 "%host%" | findstr /r /c:"[0-9] *ms"
if %errorlevel% == 0 (
echo Success.
) else (
echo FAILURE.
)
This works by checking whether a string such as 69 ms or 314ms is printed by ping.
(Translated versions of Windows may print 42 ms (with the space), hence we check for that.)
Reason:
Other proposals, such as matching time= or TTL are not as reliable, because pinging IPv6 addresses doesn't show TTL (at least not on my Windows 7 machine) and translated versions of Windows may show a translated version of the string time=. Also, not only may time= be translated, but sometimes it may be time< rather than time=, as in the case of time<1ms.
If you were to
echo "Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),"
you would see the % is stripped. You need to escape it as % has a special meaning within a batch file:
"Packets: Sent = 4, Received = 4, Lost = 0 (0%% loss),"
However its simpler to use TTL as the indication of success;
.. | find "TTL"
Testing for 0% loss may give a false positive, in this scenario:
Let's say you normally have a network drive on some_IP-address, and you want to find out whether or not it's on.
If that drive is off, and you ping some_IP-address, the IP address from which you ping, will respond:
Answer from your_own_IP-address: target host not reachable
... 0% loss
You might be better off using if exist or if not exist on that network location.
I 'm not exactly sure what the interaction between FIND and setting the error level is, but you can do this quite easily:
#echo off
for /f %%i in ('ping racer ^| find /c "(0%% loss)"') do SET MATCHES=%%i
echo %MATCHES%
This prints 0 if the ping failed, 1 if it succeeded. I made it look for just "0% loss" (not specifically 4 pings) so that the number of pings can be customized.
The percent sign has been doubled so that it's not mistaken for a variable that should be substituted.
The FOR trick serves simply to set the output of a command as the value of an environment variable.
Another variation without using any variable
ping racer -n 1 -w 100>nul || goto :pingerror
...
:pingerror
echo Host down
goto eof
:eof
exit /b
Yes ping fails to return the correct errorlevel. To check the network connection and the computer I used "net view computername" then checked %errorlevel% - simple and easy
First of all
>#echo off
>for /f %%i in ('ping racer ^| find /c "(0%% loss)"') do SET MATCHES=%%i
>echo %MATCHES%
Does not work. If it won't fail, it will detect 0%, because it has 0%.
If it fails, does not work either, because it will have 100% loss, which means, it found the 0% loss part behind the 10
10(0% loss)
Have it detect for 100% loss like so:
>for /f %%i in ('ping -n 1 -l 1 %pc% ^| find /c "(100%% loss)"') do SET check=%%i
Errorlevel might be a bit messed up, but it works like a charm:
>if '%check%'=='1' goto fail
>if '%check%'=='0' echo %pc% is online.&goto starting
1 means it failed
0 means it succeeded
In my script is use links.
Goto fail will go to :fail in my script which will message me that %pc% (which I'll have the user input in the beginning) is offline and will go for another run.
>:fail
>color 0c
>title %pc% is offline
>echo %pc% is offline
>PING -n 6 127.0.0.1>nul
>goto choice
I hope this helps.
The most simple solution to this I can think of:
set error=failure
ping racer -n 1 -w 100>nul 2>&1 && set error=success
Of course, -w needs to be adjusted if on a slow link (100ms might be too short over Dialup ;-))
regards
ping has an errorlevel output value. Success is 0, failure is 1.
Just do this:
C:\>ping 4.2.2.2
Pinging 4.2.2.2 with 32 bytes of data:
Reply from 4.2.2.2: bytes=32 time=28ms TTL=57
Reply from 4.2.2.2: bytes=32 time=29ms TTL=57
Reply from 4.2.2.2: bytes=32 time=30ms TTL=57
Reply from 4.2.2.2: bytes=32 time=29ms TTL=57
Ping statistics for 4.2.2.2:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 28ms, Maximum = 30ms, Average = 29ms
C:\>echo %errorlevel%
0
C:\>ping foo.bar
Ping request could not find host foo.bar. Please check the name and try again.
C:\>echo %errorlevel%
1
As you can see there is no need for all this scripting overkill.
Based on Alex K's note, this works for me on Windows 7:
#echo off
setlocal enableextensions enabledelayedexpansion
for /f %%i in (PCS.TXT) do (
SET bHOSTUP=0
ping -n 2 %%i |find "TTL=" > NUL && SET bHOSTUP=1
IF !bHOSTUP! equ 1 (
CALL :HOSTUP %%i
) else (
CALL :HOSTDOWN %%i
)
)
GOTO EOF
:HOSTUP
echo Host UP %1
GOTO EOF
:HOSTDOWN
echo Host DOWN %1
GOTO EOF
:EOF
exit /B
ping 198.168.57.98 && echo Success || echo failed
I liked the concept of the FIND in the ping results but why not just FIND the Reply from the Address being pinged?
In the example below I enter an IP address as a variable, PING that IP, then look for that variable in the reply string, using the FIND Command.
If the Reply String contains anything other than the correct IP it reports failure.
If you want you can just read the value of ERRORLEVEL from the FIND.
That will give you a reliable value to work with.
#echo off
Set /P IPAdd=Enter Address:
cls
ping %IPAdd% | find "Reply from %IPAdd%:"
if not errorlevel 1 set error=success
if errorlevel 1 set error=failure
cls
echo Result: %error%
pause
I needed to reset a wifi connection because it has issues. This was my quick solution.
#echo off
Rem Microsoft Windows 10 ping test to gateway.
Rem Run batch file from an administrative command prompt.
cls
:starting
Rem Send one ping to the gateway. Write the results to a file.
ping 192.168.1.1 -n 1 > pingtest.txt
Rem Search for unreachable in the file.
c:\windows\system32\findstr.exe "unreachable" pingtest.txt
Rem errorlevel 0 reset the adapter if 1 then wait 10 minutes and test again
if %errorlevel%==1 goto waiting
Rem unreachable was found reset the adapter.
Rem write the date and time the reset was done.
echo Reset date: %date% time: %time% >> resettimes.txt
Rem issue netsh interface show interface to find your adapter's name to reset
Rem my adapter is "wi-fi"
netsh interface set interface "wi-fi" disable
timeout /t 5
netsh interface set interface "wi-fi" enable
:waiting
echo "It is online waiting 10 minutes"
timeout /t 600
goto starting

Script to start traceroute if continuous ping fails, output to log

I want to continuously ping my home public IP address, and if the ping fails automatically do a traceroute to see where it's failing.
I've been trying to follow the comments made here:
http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/efc97c66-60a6-4fd7-8be4-4b454d040ce5
Windows compatible would be preferable, bat or vbs would be best.
From anywhere on the internet I will lose my connection to my home network. From work I have started a ping and when it drops I've done a traceroute and it fails before it gets to my IP.
I need a log file to prove that it is not my modem, or router, or computer.
#echo off
set Address=google.com
:Loop
PING -n 5 127.0.0.1>nul
echo Pinging %Address%
%SystemRoot%\system32\ping.exe -n 1 %Address% | %SystemRoot%\system32\find.exe "TTL=" > NUL >> C:\pingtest\logfile.log
if %ERRORLEVEL% EQU 0 goto :Loop
echo Trace route %Address% at %date% %time% >> C:\pingtest\logfile.log
tracert %Address% >> C:\pingtest\logfile.log
goto Loop
This is what I ended up going with, if anyone else ever needs this. Essentially the "Ping -n 127.0.0.1>Nul" is to add a 5 second counter so that it only pinged the destination every 5 seconds, 5 can be changed to whatever value is needed.
Windows 7 has this problem where a ping may result with something like "reply from 192.168.1.5: Destination host unreachable". So instead of erroring out it gets a reply from itself and not the error level 1.
Instead of looking for Error Level 1 I choose to look for no result for TTL with "%SystemRoot%\system32\ping.exe -n 1 %Address% | %SystemRoot%\system32\find.exe "TTL=" > NUL"
Anyway, I'm sure the other answers here were very similar and may have worked, so I am ranking them up, but marking this as the answer.
Thanks all!
#echo off
set Address=www.google.com
set LogDir=C:\pingtest
md %LogDir%
%SystemRoot%\explorer.exe "%LogDir%"
echo PingTest script to monitor network connection. Control-C to exit.
echo Tests connection by pinging %Address%. Logs to %LogDir%\logfile.log.
echo %date% %time% Initial tracert (trace route) to %Address% >> %LogDir%\logfile.log
tracert %Address% >> %LogDir%\logfile.log
:Loop
REM 5 second delay
PING -n 5 -w 1 127.0.0.1>nul
echo %date% %time% Pinging %Address%
echo %date% %time% Pinging %Address% >> %LogDir%\logfile.log
%SystemRoot%\system32\ping.exe -n 1 %Address% | %SystemRoot%\system32\find.exe "TTL=" > NUL
if %ERRORLEVEL% EQU 0 goto :Loop
echo %date% %time% PING ERROR - Tracing route to %Address%
echo %date% %time% PING ERROR - Tracing route to %Address% >> %LogDir%\logfile.log
tracert %Address% >> %LogDir%\logfile.log
goto Loop
You could make a simple batch file that tries a ping and if it fails does a tracert, eg:
setlocal
set host=www.bigpond.com
set logfile=nettest.log
echo %date% %time%>>%logfile%
ping %host%>>%logfile%
if ERRORLEVEL 1 tracert %host%>>%logfile
endlocal
There's plenty of scope for refinement here.
Then create a scheduled task that runs it every five minutes or whatever suits you.
Alternatively you could include a loop with a 'sleep' in it. There's a poor man's sleep at Sleeping in a batch file that uses:
choice /d y /t 5 > nul
:LOOP
FOR /F "usebackq tokens=1" %%F IN (`ping localhost -n 1 -w 1 ^| find "Request"`) DO (
IF "%%F"=="Request" (
tracert localhost
)
)>>log.txt
FOR /F "usebackq tokens=1-4 delims=:." %%G IN (`echo %time%`) DO IF %G%H GTR 1400 GOTO:EOF
GOTO LOOP
Basically, this states do ping, if it finds a line that has an instance of the word Request (which only appears if you can't ping the address) perform a tracert. The -n and -w switches in PING tell it to jump only once and timeout after 1 second of not getting a response. This is perfectly fine if you are pinging your localhost. The second FOR statement is to have a stopping point. Change the 1400 to a time you wish for the script to stop (in military time of course).
I have just been looking for the same thing to investigate why a VPN keeps dropping on a wired connection, used one of the batch file suggestions above which was great.
Also found a nice little Java App which packages it for you here
Internet Connectivity Monitor
Simple to use and does the job :-)

Resources