#!/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin CONFIG=$1 WEIGHT=2 #Weight value of non-200 responses #Alias DB command for easy future adjustments SQL='sqlite3' # Check for dependencies if ! which $SQL >/dev/null 2>&1; then printf '%s\n' "ERROR 12: Missing dependency -- '$SQL' command not found." >&2 exit 12 fi if ! which curl >/dev/null 2>&1; then printf '%s\n' "ERROR 12: Missing dependency -- 'curl' command not found." >&2 exit 12 fi # BEGIN CONFIG CHECK ### Provides KEY, CHATID, CHKLIST if [ -n "$CONFIG" ]; then if [ -f "$CONFIG" ]; then . $CONFIG #Source config file else printf '%s\n' "$CONFIG: File does not exist." >&2 exit 10 fi else if [ -f ".httpcheck_telegram" ]; then . .httpcheck_telegram #Source config file else printf '%s\n' "No configuration file found." >&2 exit 10 fi fi W_MAX=$(( $WEIGHT * $MAX_COUNT )) # Check if config was loaded by examining all configuration variables, exit if not if [ -z "$KEY" ]; then printf '%s\n' "Configuration not set correctly: KEY not set" >&2 ERROR11=true fi if [ -z "$CHATID" ]; then printf '%s\n' "Configuration not set correctly: CHATID not set" >&2 ERROR11=true fi if [ -z "$CHKLIST" ]; then printf '%s\n' "Configuration not set correctly: CHKLIST not set" >&2 ERROR11=true fi if [ -z "$DB" ]; then printf '%s\n' "Configuration not set correctly: DB not set" >&2 ERROR11=true fi if [ -z "$MAX_COUNT" ]; then printf '%s\n' "Configuration not set correctly: MAX_COUNT not set" >&2 ERROR11=true fi [ "$ERROR11" = "true" ] && exit 11 # END CONFIG CHECK #DB functions db_create() { $SQL $DB "CREATE TABLE problem ( site TEXT UNIQUE NOT NULL, count INT NOT NULL DEFAULT 0, alert INT NOT NULL DEFAULT 0, sent INT NOT NULL DEFAULT 0 );" || return 1 } db_addsite() { $SQL $DB "INSERT OR IGNORE INTO problem (site) VALUES('$1');" } db_rmsite() { $SQL $DB "DELETE FROM problem WHERE site = '$1';" } db_inc() { $SQL $DB "UPDATE problem SET count = count + $WEIGHT WHERE site = '$1' AND count < $W_MAX;" if [ $($SQL $DB "SELECT count FROM problem WHERE site = '$1';") -ge $W_MAX ]; then $SQL $DB "UPDATE problem SET alert = 1 WHERE site = '$1';" fi # Correct values above $W_MAX, possible due to the implementation of weight. if [ $($SQL $DB "SELECT count FROM problem WHERE site = '$1';") -gt $W_MAX ]; then $SQL $DB "UPDATE problem SET count = $W_MAX WHERE site = '$1';" fi } db_dec() { # Add weight only if alert state is active, allowing alerts to clear in the expected time frame. if [ $($SQL $DB "SELECT alert FROM problem WHERE site = '$1';") -eq 1 ]; then $SQL $DB "UPDATE problem SET count = count - $WEIGHT WHERE site = '$1' AND count > 0;" else $SQL $DB "UPDATE problem SET count = count - 1 WHERE site = '$1' AND count > 0;" fi if [ $($SQL $DB "SELECT count FROM problem WHERE site = '$1';") -le 0 ]; then $SQL $DB "UPDATE problem SET alert = 0 WHERE site = '$1';" fi # Correct values below zero, possible due to the implementation of weight. if [ $($SQL $DB "SELECT count FROM problem WHERE site = '$1';") -lt 0 ]; then $SQL $DB "UPDATE problem SET count = 0 WHERE site = '$1';" fi } TIME="10" URL="https://api.telegram.org/bot$KEY/sendMessage" #Telegram message function send_message() { curl -s --max-time $TIME -d "chat_id=${CHATID}&disable_web_page_preview=1&text=$1" $URL >/dev/null } get_http_code() { if host $(printf '%s\n' $1 | awk '{gsub("https?://|/.*","")}1') 2>&1 >/dev/null; then curl -sILk --max-time $TIME $1 | grep HTTP | tail -n 1 | grep -Eo '[0-9]{3}' || printf '%s\n' 999 else printf '%s\n' 000 fi } read_checklist() { grep -v "^#\|^$" $CHKLIST | sort | uniq || return 1 } print_time() { date '+%Y-%m-%d %H:%M:%S' } # Prepare message header #MSG="${HEADER}%0AProblems Found:" FAILURE=false # Create database if it doesn't exist if [ -f $DB ]; then printf '%s\n' "Database found: $DB" # Remove stale entries in DB no longer found in check list printf '%s\n' "Pruning database..." for row in $($SQL $DB "SELECT site FROM problem;"); do if ! read_checklist | grep $row >/dev/null 2>&1; then db_rmsite "$row" && printf '%s\n' "Removing old record: $row" fi done printf '%s\n' "Database pruning complete." else printf '%s' "Database not found at '$DB'\nCreating DB ... " if db_create; then printf '%s\n' "DONE" else printf '%s\n' "FAILED" printf '%s\n' "Database creation failed!" >&2 exit 13 fi fi # Check HTTP codes for site in $(read_checklist); do db_addsite $site respcode=$(get_http_code $site) case $respcode in 000) printf '%s\n' "[$(print_time)]: PROBLEM -- $site: DNS record not found" >&2 db_inc $site #MSG="${MSG}%0A%0A %2B ${site}%0A DNS record not found" #FAILURE=true ;; 200) printf '%s\n' "[$(print_time)]: OK -- $site returns $respcode" db_dec $site ;; 999) printf '%s\n' "[$(print_time)]: PROBLEM -- $site caused general cURL failure" >&2 db_inc $site ;; *) printf '%s\n' "[$(print_time)]: PROBLEM -- $site returns $respcode" >&2 db_inc $site #MSG="${MSG}%0A%0A %2B ${site}%0A Responding ${respcode}" #FAILURE=true ;; esac done || exit 2 # Find down sites without sent alerts unsent=$($SQL $DB "SELECT count(*) FROM problem WHERE alert = 1 AND sent = 0;") cleared=$($SQL $DB "SELECT count(*) FROM problem WHERE alert = 0 AND sent = 1;") down=$($SQL $DB "SELECT count(*) FROM problem WHERE alert = 1;") downlist=$($SQL $DB "SELECT site FROM problem WHERE alert = 1;" | perl -p -e 's/\n/%0A/g') # If ANY sites have unsent alerts, send a list of ALL sites in 'alert' state if [ $unsent -gt 0 ]; then ALERT="${HEADER}%0ASites Down:%0A${downlist}" send_message "$ALERT" && printf '%s\n' "Problems found. Message sent via Telegram bot" >&2 || printf '%s\n' "Problems found. Message sending has failed" $SQL $DB "UPDATE problem SET sent = 1 WHERE sent = 0 AND alert = 1;" #Prevents resending messages fi # If ALL sites have cleared alerts, send an all-clear if [ $cleared -gt 0 ]; then clearlist=$($SQL $DB "SELECT site FROM problem WHERE alert = 0 AND sent = 1;" | perl -p -e 's/\n/%0A/g') CLEARED="${HEADER}%0AThese HTTP alerts have cleared:%0A${clearlist}" if [ $down -gt 0 ]; then CLEARED="${CLEARED}%0ASites still down:%0A${downlist}" fi send_message "$CLEARED" && printf '%s\n' "A site's alert status has cleared. Message sent via Telegram bot" >&2 || printf '%s\n' "A site's alert status has cleared. Message sending has failed" $SQL $DB "UPDATE problem SET sent = 0 WHERE sent = 1 AND alert = 0;" #Prevents resending messages fi exit 0