Use PING to notify when server reboots.

Working on servers, you inveriably need to reboot them. One of the primary tools I use to determine if a server has shut down is to PING the server.

PING servername -t

This will PING the server repeatedly until I quit it. When the server goes down, it will return "Request Timed Out" instead of a valid PING response. Here is what it would look like when the server shuts down, then comes back up again.

Pinging Servername [192.168.1.1] with 32 bytes of data:
Reply from 192.168.1.1: bytes=32
Reply from 192.168.1.1: bytes=32
Reply from 192.168.1.1: bytes=32
Reply from 192.168.1.1: bytes=32
Reply from 192.168.1.1: bytes=32
Request timed out
Request timed out
Request timed out
Request timed out
Request timed out
Reply from 192.168.1.1: bytes=32
Reply from 192.168.1.1: bytes=32
Reply from 192.168.1.1: bytes=32

Unfortunately, if you happen to miss the downtime (change screens, leave your desk, etc.) you'll never know what happened. Did the server reboot or has Windows crashed while trying to go down???

That's why I developed this little batch script. It utilizes the DOS PING command to monitor the status change. When the server successfully shuts down, it changes the display and waits for the server to come back up.


Checking Server [servername] for response
Check # 0 - Server Down: 16:32:27.89
Waiting For Server to come up: 4
Server Pinging Again Passes: 5

Highlight and copy the following code to your buffer (CTRL+C). Open notepad, and paste it into a new text file. Save that text file as PingAlive.bat. Copy this file into your system path (like C:\Windows\System32).




echo off
CLS
Set A=0
Set ServerName=%1

if not '%1'=='' goto :Pass1
Set /p ServerName=[What is the server name?]
if not '%ServerName%'=='' goto :Pass1
echo Failed to get Server name..
Goto :End

:Pass1
Echo Checking Server %ServerName% for response
echo Check # _
:Pass1a
ping %ServerName% > results.txt
find /C "Request timed out" results.txt > fresults.txt

for /F "skip=1 tokens=1,2 delims=:" %%a in (fresults.txt) DO (
if NOT "%%b"==" 0" goto :TimedOut
cls
Echo Checking Server %ServerName% for response
echo Check # %A%
Set /A A+=1
Goto :Pass1a
)
:TimedOut
Set DownTime=%TIME%
Echo Server Down %DownTIME% Passes: %A%
Set B=0
:Pass2
ping %ServerName% > results.txt
find /C "Request timed out" results.txt > fresults.txt
for /F "skip=1 tokens=1,2 delims=:" %%a in (fresults.txt) DO (
if "%%b"==" 0" goto :BackUp
CLS
Echo Checking Server %ServerName% for response
echo Check # %A% - Server Down: %DownTime%
Echo Waiting For Server to come up: %B%
Set /A B+=1
Goto :Pass2
)

:BackUp
echo Server Pinging Again - Passes: %B% %TIME%
:End



Now when you reboot a server, simply open a new command window and type:


PINGALIVE SERVERNAME

Now I can use my server reboots as coffee breaks and not worry about missing anything!

Another great use for PSExec

Tired of searching through racks and racks of servers to not find what your looking for?

Tired of having to run back to your desk to remote into that server to insert a CD?

Utilizing the power of PSExec, you can eject the CD drive remotely without having to leave your comfy desk.


@echo off
if "%1"=="" goto end
echo Starting process to eject the CD on %1
psexec \\%1 -c "\\yourworkstationname\script$\ejectcd.exe"
:end

Hello? Is anyone out there? If so, ping me..

When you are looking for something, like a piece of hardware, and you don't know where to start looking, it is always useful to have a good set of tools.

For example, I wanted to find what IP address that a new UPS device was using. I could not locate it in the DHCP tables and figured it must have a static IP address. The administration tools could not access it via the USB cable, so I needed to brute force search for the IP address. What I would do for an IP scanner right then? Code one!

The script below is a command-line script that uses WMI to check the pingstatus of the system at each IP address. I grabbed parts from Windows IT Pro. So far, it will only increment the last octet of the IP address. Maybe if the need arises, I will modify the code to take a start and end range.

Update:
After reviewing Scott's enormous list of his favorite tools, I found this one which appears to have a great GUI.


' Ping Range Script (PingIP.vbs)
' By Eric Woodford (http://www.ericwoodford.com)
' Original Source from http://www.windowsitpro.com/Article/ArticleID/48449/48449.html

Option Explicit

Dim strHost, strEnd
Dim Start_IP, x, strIP

' Check that all arguments required have been passed.
If Wscript.Arguments.Count < 1 Then
Wscript.Echo "Arguments required. For example:"
Wscript.Echo "Ping a single IP address or hostname:"
Wscript.Echo vbtab& "cscript PingIP.vbs (hostname)"
Wscript.Echo vbtab& "cscript PingIP.vbs ipaddress" & vbcrlf
Wscript.Echo "Ping a range of IP addresses from ipaddress to ipaddress+count"
Wscript.Echo vbtab& "cscript vbping.vbs ipaddress count"
Wscript.Quit(0)
End If

strHost = Wscript.Arguments(0)
if wscript.arguments.count = 2 then
strEnd = wscript.arguments(1)
if not(isnumeric(strend)) then
wscript.echo "Count argument needs to be numeric (1-254)."
wscript.quit
end if
if cint(strend)>=254 or cint(strend)<=0 then
wscript.echo "Count argument needs to be numeric (1-254)."
wscript.quit
end if
strEnd=cint(strEnd)
end if
if strEnd <> "" then
'get last subnet of start
strIP = left(strHost,instrrev(strHost,"."))
Start_IP = right(strhost,len(strHost)- instrrev(strHost,"."))
if isnumeric(start_IP) then
start_ip=cint(start_ip)
else
wscript.echo "ERROR: To ping a range, you need to put in the starting IP address, not a hostname"
wscript.quit(0)
end if
if start_ip = 0 then start_ip = 1
wscript.echo start_ip + strEnd
if (Start_IP + strEnd) > 255 then
wscript.echo "range exceeds maximum for octet."
strEnd= strend - ((start_ip+strend)-255)
wscript.echo "converting max of range to :" & strEnd
end if
for x = start_IP to (start_ip + strEnd)
if Ping(strIP&x) = True then
Wscript.Echo "Host " & strIP&x & " contacted"
Else
Wscript.Echo "Host " & strIP&x & " could not be contacted"
end if
next
Else
if Ping(strHost) = True then
Wscript.Echo "Host " & strHost & " contacted"
Else
Wscript.Echo "Host " & strHost & " could not be contacted"
end if
End If

Function Ping(strHost)

dim objPing, objRetStatus

set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery _
("select * from Win32_PingStatus where address = '" & strHost & "'")

for each objRetStatus in objPing
if IsNull(objRetStatus.StatusCode) or objRetStatus.StatusCode<>0 then
Ping = False
'WScript.Echo "Status code is " & objRetStatus.StatusCode
else
Ping = True
'Wscript.Echo "Bytes = " & vbTab & objRetStatus.BufferSize
'Wscript.Echo "Time (ms) = " & vbTab & objRetStatus.ResponseTime
'Wscript.Echo "TTL (s) = " & vbTab & objRetStatus.ResponseTimeToLive
end if
next
End Function

Function Resolve(strHost)

dim objPing, objRetStatus

set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery _
("select * from Win32_ComputerSystem where address = '" & strHost & "'")

for each objRetStatus in objPing
if IsNull(objRetStatus.StatusCode) or objRetStatus.StatusCode<>0 then
Resolve = ""
'WScript.Echo "Status code is " & objRetStatus.StatusCode
else
Resolve = True
'Wscript.Echo "Bytes = " & vbTab & objRetStatus.BufferSize
'Wscript.Echo "Time (ms) = " & vbTab & objRetStatus.ResponseTime
'Wscript.Echo "TTL (s) = " & vbTab & objRetStatus.ResponseTimeToLive
end if
next
End Function

Pipes, not just for plumbers.

For quite some time, I have wanted to develop a batch script that I could use to automate the process of backing up my documents then email them to myself. Using my GMail account's enormous capacity, I can keep several copies of my documents accessible online without having to worry about drive space.

My requirements:

  1. Compression needs to be a standard format. (ZIP, TAR, etc.) I want the option to access these files using any computer.
  2. Need to be able to filter out files or include only specific files (not just the entire folder). I have a few large databases, that I wouldn't want to be sent. No matter what, I don't want this 2gb Access database sent to me.
  3. Automated. I want this to happen on a regular basis, without me having to initiate it. Backups are useless if you can't rely on them.
  4. Sent to me via email. As I stated, I want this to be emailed to me, instead of sitting on the computer I ran it from.

Here is the code that I came up with. I make use of DOS pipes in order to get my data.

dir /b /s /AA "%userprofile%\my documents\" | find "My Shapes" /v | find "My Pictures" /v | find "My Videos" /v | c:\bin\zip232xn\zip c:\My_Stuff.zip -@ >> c:\my.log

The DIR command displays the directory in BARE format (path and filename only), only show files with the Archive bit turned on, and search sub-folders. The FIND statement, searches the filenames given it, and excludes entries that contain the search string (like "My Shapes"). Finally Info-Zip takes the filename and compresses it into a single file, C:\My_Stuff.zip.

When that is complete, I run the DOS Attrib command to turn off the attribute bit on all the files I compressed. Then I email myself the file using BLAT. Note, that I have set it to span the email into multiple 10mb attachments. You'll need to adjust this to match your outgoing SMTP server, and use an email program that can handle multipart UUEncoded attachments.

You'll need:

The full script is below.


Echo off
echo %DATE% %TIME% > c:\my.log

dir /b /s /AA "%userprofile%\my documents\" | find "My Shapes" /v | find "My Pictures" /v | find "My Videos" /v | c:\bin\zip232xn\zip c:\My_Stuff.zip -@ >> c:\my.log
if "%errorlevel%"=="0" attrib -A /s /D "%userprofile%\my documents\*.*" >> c:\my.log

REM Repeat code above for additional folders. For example a server side share.

:send
C:\BIN\blat262\full\blat.exe c:\my.log -to example@gmail.com -server mail -Subject "Stuff from %date% %time%" -f MyFromAddress@example.com -attach c:\my_stuff.zip -multipart 10240

if "%errorlevel%"=="0" del c:\my_stuff.zip
del c:\my.log

Playing with PSInfo

Now that Daylight Saving Time has begun, I am constantly getting requests for help on why the calendar info is wrong. I suggest that maybe they need to install the Microsoft patch (931836). Unfortunately it is not easy to scan a computer to find a single patch. Since Service Pack 2, there has been at least 150 patches for various issues, updates, and such.

To make things easier, I found that the PSInfo will return all the patches for a specific computer. This will return all the patches on the local computer. Unfortunately, it does not appear that you can filter on a specific patch using the embedded 'filter' command of PSInfo (like you can for other components that it will return).

PSInfo -h
----------------------------------
Installed HotFix
8/28/2006 Microsoft .NET Framework 1.1 Hotfix (KB886903)
8/27/2006 Microsoft .NET Framework 1.1 Service Pack 1 (KB867460)
10/14/2006 This Security Update is for Microsoft .NET Framework 2.0. \n
(etc.)

Great! Now I can have my Dad wade through 3 pages of hotfixes, looking for a specific number in the list. Of course, I can have him pipe it to a text file, then simply search the file in Notepad or such. Why? DOS has a great command called "FIND". This command will search an input source and return matching contents. So I have them type in:

PSInfo -h | find "931836"

This returns one line when it finds the patch:

PsInfo v1.74 - Local and remote system information viewer
Copyright (C) 2001-2005 Mark Russinovich
Sysinternals - www.sysinternals.com

2/17/2007 Update for Windows XP (KB931836)

and no patch info when it is not installed.

To extend this, I have considered taking advantage of the wildcard functionality in PSInfo. You could type "\\*" after the PSINFO statement and it would search all computers on the local network! Unfortunately, I've been told that this returns the number of computers with a give patch, not which ones. I'd suggest a BATCH FOR ... loop..

Thanks Mark, I love PSTools!

Using Ping to Notify when a Server Reboots v2.

Working on network workstations, I found I needed a method to tell when they came online. I wanted a script to email me so I could receive it on my PDA when the connection worked. This way I could be working in the wiring cabinet and hear it successfully connect.

The following script can easily be modified to notify when a server is up or down. I've also added an option to loop the script continuously until specific triggers are met. These triggers can be set at the command line, or hard set into the code for quick deployment. You'll just need to put your email address into the script before you run it.

Requirements: Latest version of BLAT (note the path in line 75).


@echo off
REM ======================================================================
REM
REM Batch File -- Created with SAPIEN Technologies PrimalScript 3.1
REM
REM NAME: NOTIFY.BAT
REM
REM AUTHOR: Eric Woodford
REM DATE : 2/13/2008
REM
REM COMMENT: This script can be configured to notify when a specific server is up or down
REM requires BLAT to send SMTP email messages.
REM ======================================================================
cls

set dest=%1
if '%dest%'=='' goto :error

REM address to notify when triggered.
Set emailaddr=eric@example.com
set mailsrvr=mail.example.com

if not '%2'=='' goto :params
rem set this to 1 to trigger when true
set exitwhenup=0
set notifyup=0
set exitwhendown=1
set notifydown=1
goto :repeat

:params
set exitwhenup=%2
set notifyup=%3
set exitwhendown=%4
set notifydown=%5

:repeat

if exist c:\notifydown.txt del c:\notifydown.txt
ping %dest% -n 1 | find /c "Reply from " > c:\NotifyDown.txt

for /F "tokens=1" %%a in (c:\notifydown.txt) DO (
set /A serverstatus=%%a
if '%serverstatus%'=='1' (
set msgsubject=Server Up - %time%
cls && echo %msgsubject%
if '%notifyup%'=='1' call :sendmsg
if '%exitwhenup%'=='1' goto :exit
) ELSE (
set msgsubject=Server Down - %time%
cls && echo %msgsubject%
if '%notifydown%'=='1' call :sendmsg
if '%exitwhendown%'=='1' goto :exit
)
)

goto :repeat

:error
echo %0 - Notify when device is down
echo.
echo parameters:
echo 1. IP address or host name
echo.
echo [Optional]
echo 2. Exit when up (0=no, 1=yes)
echo 3. Notify when up (0=no, 1=yes)
echo 4. Exit when down (0=no, 1=yes)
echo 5. Notify when down (0=no, 1=yes)

goto :exit

:sendmsg
REM This is all one line, upto the GOTO statement.
call c:\bin\blat262\full\blat.exe c:\notifydown.txt -t %emailaddr% -server %mailsrvr% -f %emailaddr% -subject "%dest% %msgsubject%"
goto :EOF

:exit
echo exiting %time%