Monitoring Website for Downtime

Sometimes our in house server go down, But at production level we cannot take risk of 1min downtime, so we were supposed to monitor our server for downtime.
Although there are many cheap services available but i decided to do it my own way, I can use this script in my RPI to monitor even my internal services.

Below is python code, Which sends email if a server goes down and when it comes back online. Obviously you can add code to get more statistics like Logging to file, average response time, Monitoring page changes, Downtime etc.

import httplib
import time
from smtplib import SMTP

def send_email(to,subject,body,SERVER="smtp.gmail.com",PORT=587,USERNAME="[email protected]",PASSWORD="YourPassword"):
	smtp = SMTP(SERVER, PORT)
	smtp.ehlo()
	smtp.starttls()
	smtp.login(USERNAME, PASSWORD)
	headers = "\r\n".join(["from: " + USERNAME,
                       "subject: " + subject,
                       "to: " + to,
                       "mime-version: 1.0",
                       "content-type: text/html"])
                    
	content = headers + "\r\n\r\n" + body
	smtp.sendmail(USERNAME, to, content)



def get_status_code(host,path="/"):
	try:
		conn = httplib.HTTPConnection(host,timeout=10)
		conn.request("HEAD",path)
		return conn.getresponse().status
	except StandardError:
		return 0


def get_site_status(host):
	start = time.time()
	status = False
	code = get_status_code(host)
	#if found, temp redirect, permanent redirect.
	if code in (200,302,301):
		status = True
	return status, time.time()-start,code


def check_internet():
	return get_site_status("google.com")

def check_status():
	toMonitor = ["tikaj.com"]
	down = []
	email = ""
	while True: 
		for value in toMonitor:
			st = "Checking %s..." %value

			#give enough space so that status code can be idented.
			while(len(st)<40):
				st += " "
			print st,

			status,rtime,code = get_site_status(value)
			print "[%s]" %code,

			if status==False :
				if check_internet()[0] == True :
					print "[Server down]"
					
					#if not present in Server down list. Add for email and add to down list.
					if value not in down:
						down.append(value)
						email += st + "<b>[SERVER_DOWN]</b><br/>"
				else:
					print "[Internet Fail]"
			else: 
				# if in down list compose mail that server is up.
				if value in down:
					email += st + "<b>[%fs]</b>" %rtime
					down.remove(value)
				print "[%fs]" %rtime


		if(len(email)>10):

			print "Sending alert email..."
			send_email("[email protected]","ServerDown!","<pre>%s</pre>" %email)
			email = ""

		time.sleep(60) #sleep for 60s

if __name__ == '__main__':
	check_status()

After saving code to server use cron job to start run script on every boot.

Edit crontab using `sudo crontab -e` and then add following line to file.

`@reboot screen -dmS monitor python /root/monitor.py &> /dev/null`

Above command starts a `screen` session named monitor and forwards error of screen to null.
Incase you want to see output of monitor.py use `screen -r monitor`.
You can also add it simply without screen like
`@reboot python /root/monitor.py &`

If you have some suggestions comment.

Simple automatic versioning using git

Many times while working on projects its hard to keep track of which version is in staging server, which is on production and which other developers of team are working on, Especially when you are a small startup with limited number of resources. (Its really painful to setup automatic deployment in gitlab).

Here is what i started following in every project :
Version of server should increase with number of commits, major increments will be done manually based on release date, number of issues solved. For automatic commit based versioning add following lines to `.git/hooks/pre-commit`.

`git add Version && echo $(cat Version)+0.0001 | bc | awk ‘{printf “%0.4f”, $0 > “Version”}’`

Also make sure that file is executable by

`chmod +x .git/hooks/pre-commit`

I follow following version numbering system :
– `+1.00000` – Major version
– `+0.1` – Minor Version
– `+0.0001` – Commit

Hello World !

First post for friends, family & love.