#StandWithUkraine

Checking and logging server uptime with AutoIt

AutoIt Peter Owen of String of Theories had asked in comments for PingInfoView post if it can mail when pinging fails.

I could use something like that myself and indulged today in coding AutoIt script that can perform multiply types of check on remote server and log results. Only downside it can’t mail either. :)

Disclaimer

I am not too good with network programming. So this one turned out to be slightly clunky and not guaranteed to be bulletproof.

Task

I wanted something that checks if server is alive in specific intervals and logs changes only (not every check but when situation changes from what it was).

Since I wanted it flexible – ended up coding three checks (with room for more):

  • ping;
  • TCP header check which splits in check for
    • HTTP web server;
    • FTP server.

Main loop

#include <Date.au3>
Dim Const $host = "localhost"
Dim Const $wait = 5 * 60 * 1000
Dim Const $log = @ScriptDir & "\uptime.log"
Dim $laststatus = False

Including library for date which will be used for timestamp in log.

Variables are:

  • server to monitor;
  • time between checks, calculated in milliseconds;
  • log file in same directory as script;
  • saving last state for comparing so we don’t log every check.
While 1
$status = CheckAlive($host)
If $status <> $laststatus Then
	$laststatus=$status
	$message = _Now() & " " & $host & " "
	If $status Then
		$message &= "online"
	Else
		$message &= "offline"
	EndIf
	TrayTip("Check alive", $message, 10)
	FileWriteLine($log, $message)
EndIf
Sleep($wait)
WEnd

We call function to check server (see below) and compare result to last state saved. Generic code uses default ping check so needs to be edited for advanced ones.

If situation changed it is reported via balloon tip (assuming non-ancient Windows version) and logged to file.

Then script waits for next check and repeats.

Server check

That is where actual magic happens.

Func CheckAlive($host,$method="ping",$port=False,$query="HEAD / HTTP/1.0")
Switch $method
	Case "ping"
		$ping=Ping($host)
	If $ping Then
		SetExtended($ping)
		Return True
	Else
		Return False
	EndIf
	Case "web"
		If Not $port Then $port = 80
	Case "ftp"
		If Not $port Then $port = 21
	Case Else
		Return False
EndSwitch

Only required parameter is server name. Check type defaults to ping. Port and TCP request are also set but can be re-specified as needed.

In the start method is checked. Ping is processed right away, returning result and setting @extended macro to contain actual ping value in milliseconds (handy for troubleshooting).

For web or file server check correct ports are set and script goes further.

TCPStartup()
$socket = TCPConnect(TCPNameToIP($host), $port)
If $socket = -1 Then Return False
TCPSend($socket, $query & @CRLF & "Host: " & $host & @CRLF & @CRLF)
$response = False
While Not $response
	$response = TCPRecv($socket, 1024)
WEnd
TCPCloseSocket($socket)
TCPShutdown()

This part is quite messy and you should study AutoIt docs to really get what is going on (I am still not sure I do completely). :)

We are initiating connection to server, then form and send query that casually asks what server thinks about our request.

Best case we get reply. Don’t ask what the hell that loop does – I couldn’t make it work without it. Seems there are timing issues between sending request and catching response.

$response = StringRegExp($response, "\d{3}", 1)
If @error Then Return False
$response=$response[0]
$code = StringLeft($response, 1)
SetExtended($response)
If $code > 0 And $code < 4 Then Return True
Return False
EndFunc

If we are still inside function response is checked to find three digit status code. Those mean different things for HTTP and for FTP but in general anything that starts with 1 or 2 or 3 is positive.

So if code is present it is recorded in @extended and checked for first digit with returning result accordingly.

Overall

In the end I tried but could not add email reporting to it. _INetSmtpMail function is there but didn’t work with any of my email accounts.

Still after much tinkering it seems to work nicely and I look forward to running it for few days and testing properly.

Script https://www.rarst.net/script/checkalive.au3

Related Posts

6 Comments

  • Ben Zipperer #

    Nice script! I know it's not elegant or self-contained, but you could have your script invoke blat to send the report. I usually do this to send reports from non-SBS windows servers. Blat can be found at http://www.blat.net/
  • Rarst #

    @Ben Zipperer Thanks for suggestion. I saw that one mentioned in AutoIt forums as well, will check it out. Still it's not mission critical script and I like to keep AutoIt scripts... autoitish. :)
  • Tom Thompson #

    This is not a AutoIt script but I use The Dude to accomplish the same thing. It is lightweight, free, runs as a service and is client/server based. http://www.mikrotik.com/thedude.php
  • Rarst #

    @Tom Thompson Thanks will take a look at it. :) Overall I am not too interested in whole infrasctructure monitoring. This script is more of exercise - I like to write bits of different code and modularize to have such functional snippets ready for when I need something complex done.
  • IsMyBlogWorking.com &ndash; better than ping | Rarst.net #

    [...] had played with checking if site is alive in my AutoIt script and it is harder to implement than it seems. On other hand if there is no need for continuous [...]
  • reboltutorial #

    You can send email with Rebol and if you want to monitor your server it's easier than with Autoit, it's also free even for commercial use :) http://reboltutorial.com/blog/monitor-website/ str-url: ask "url to monitor? " url: to-url str-url str-email: ask "email to notify? " email: to-email str-email forever [ if error? try [ read url ] [ ;pre-requisite: you must setup your email see here send email "Site is down." ] wait 0:10 ]