Skip to content

Instantly share code, notes, and snippets.

@kulbida
Last active August 29, 2015 14:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kulbida/07c0eabc5952b0d5b2ec to your computer and use it in GitHub Desktop.
Save kulbida/07c0eabc5952b0d5b2ec to your computer and use it in GitHub Desktop.
Monitor disk usage and send notifications emails when it fills up. Script written in Go lang that can be compiled to executable file and run as a demon on the server. It will check the hdd every hour and will send emails with cycle of 1, 2, 4, 8, 16 and 32 hours.
package main
import (
"syscall"
"os"
"fmt"
"log"
"net/mail"
"encoding/base64"
"net/smtp"
"sync"
"time"
)
type MailerStruct struct {
mb_available uint64
mb_at_least uint64
send_mail_to string
smtp_credentials string
wait_group sync.WaitGroup
}
func SendEmail(wrapper *MailerStruct) {
defer wrapper.wait_group.Done()
fmt.Println("Sending notifications to ", wrapper.send_mail_to, "...")
smtpServer := "smtp.postmarkapp.com"
auth := smtp.PlainAuth(
"",
wrapper.smtp_credentials,
wrapper.smtp_credentials,
smtpServer,
)
from := mail.Address{"To email", "example@domain.com"}
to := mail.Address{"SystemUser", wrapper.send_mail_to}
title := "Alert: System Status Check."
body := fmt.Sprintf("<h3>Hi there,</h3> <p> Hard drive is almost full.</b> It only has <b>%d MBytes</b> free on device. (We should have at least %d Mb) </p>", wrapper.mb_available, wrapper.mb_at_least)
header := make(map[string]string)
header["From"] = from.String()
header["To"] = to.String()
header["Subject"] = title
header["MIME-Version"] = "1.0"
header["Content-Type"] = "text/html; charset=\"utf-8\""
header["Content-Transfer-Encoding"] = "base64"
message := ""
for k, v := range header {
message += fmt.Sprintf("%s: %s\r\n", k, v)
}
message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body))
// Connect to the server, authenticate, set the sender and recipient,
// and send the email all in one step.
err := smtp.SendMail(
smtpServer + ":25",
auth,
from.Address,
[]string{to.Address},
[]byte(message),
)
if err != nil {
log.Fatal(err)
}
}
func checkForDiskUsage(to_wait int) int {
const lower_limit_hdd_usage uint64 = 512 // mb
var stat syscall.Statfs_t
next_test_in := to_wait
wd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
syscall.Statfs(wd, &stat)
var left_megabytes uint64
left_megabytes = stat.Bavail * uint64(stat.Bsize) / 1024 / 1024
mailer_wrapper := &MailerStruct{
mb_available: left_megabytes,
mb_at_least: lower_limit_hdd_usage,
send_mail_to: os.Args[1],
smtp_credentials: os.Args[2]}
if left_megabytes < lower_limit_hdd_usage {
fmt.Println("Only ", left_megabytes, "Mb left on hard drive. We should have at least ", lower_limit_hdd_usage, " Mb.")
mailer_wrapper.wait_group.Add(1)
if to_wait >= 48 {
next_test_in = 2
} else {
next_test_in = to_wait * 2
}
go SendEmail(mailer_wrapper)
} else {
next_test_in = 1
}
mailer_wrapper.wait_group.Wait()
return next_test_in
}
func main() {
to_wait := 1 // in hours
for {
if to_wait == 1 {
fmt.Println("We have some space on HDD. Monitoring...")
} else {
fmt.Println("Next notification will be send in ", to_wait, " hours.")
}
to_wait = checkForDiskUsage(to_wait)
time.Sleep(time.Duration(to_wait) * time.Hour)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment