#!/usr/bin/env bash # State management get_state_file() { echo "/tmp/chorus-monitoring-down-hosts.txt" } is_host_down() { local type=$1 host=$2 local state_file=$(get_state_file) # If state file doesn't exist, host is not down [ ! -f "$state_file" ] && return 1 # Check if TYPE:HOST exists in state file grep -qxF "${type}:${host}" "$state_file" } mark_host_down() { local type=$1 host=$2 local state_file=$(get_state_file) # Create file if it doesn't exist touch "$state_file" # Only add if not already present (idempotent) if ! grep -qxF "${type}:${host}" "$state_file"; then echo "${type}:${host}" >> "$state_file" fi } mark_host_up() { local type=$1 host=$2 local state_file=$(get_state_file) # If state file doesn't exist, nothing to remove [ ! -f "$state_file" ] && return 0 # Remove the TYPE:HOST line from state file sed -i "\|^${type}:${host}$|d" "$state_file" } notify() { local status=$1 type=$2 host=$3 local emoji message if [[ "$status" == "DOWN" ]]; then emoji="🔴" message="$emoji [$type] $HOSTNAME says $host is DOWN. $(date -u)" else emoji="🟢" message="$emoji [$type] $HOSTNAME says $host is UP. $(date -u)" fi curl -s -d "$message" \ https://ntfy.uphillsecurity.com/thisisarandomtpic # ADD MAIL AND OTHER METHODS HERE } check_with_retries() { local type=$1 host=$2; shift 2 for _ in {1..5}; do if "$@"; then echo "$host: reply" # Check if host was previously down (state transition: DOWN → UP) if is_host_down "$type" "$host"; then mark_host_up "$type" "$host" notify "UP" "$type" "$host" fi return 0 fi sleep 1 done echo "$host: no reply after 5 attempts" # Check if host is newly down (state transition: UP → DOWN) if ! is_host_down "$type" "$host"; then mark_host_down "$type" "$host" notify "DOWN" "$type" "$host" fi return 1 } main() { # WHAT TO MONITOR hosts_icmp=("127.0.0.1" "8.8.8.8") hosts_http=("git.uphillsecurity.com" "uphillsecurity.com" "mettwork.com") hosts_tcp=("google.com:443" "uphillsecurity.com:22") # PORT REQUIRED # CHECKS for h in "${hosts_icmp[@]}"; do check_with_retries ICMP "$h" \ bash -c 'ping -c 1 -W 1 "$1" >/dev/null 2>&1' _ "$h" done for h in "${hosts_http[@]}"; do check_with_retries HTTP "$h" \ curl -s -o /dev/null --connect-timeout 1 --max-time 2 -f "https://$h" done for h in "${hosts_tcp[@]}"; do check_with_retries TCP "$h" \ bash -c 'nc -z -w 1 "$1" "$2" >/dev/null 2>&1' _ ${h%:*} ${h##*:} done } main