- #!/bin/bash
- #
- # Monitor internet/host availablility
- #
- # (c) Stin, 2021-22 - Modifed for Mark's RPi, 10/2022
- #
- ############################################
- ### Configurable parameters below:
- # Ping host <test_ip>...
- test_ip=192.168.0.10
- # Ping router <router_ip>
- router_ip=
- # ...<p_count> times...
- p_count=5
- # ...look for <f_count> failures...
- f_count=4
- # ...wait <p_tmout> seconds for a reponse...
- p_tmout=4
- # ...wait <p_delay> seconds between pings.
- p_delay=5
- ############################################
- ### Outputs:
- # Folder to save log files into:
- logdir="Allotment Connection"
- mkdir -p "$logdir"
- # 2>/dev/null 1>&2
- # Save/append state changes to a log file:
- logfile="$logdir/Allotment_Connection"
- # Or a timestamped log file:
- #logfile="./Internet_Connection_$(date +%Y%m%d-%H%M%S)"
- # Optionally, save/append ping data to a csv file (if set, comment to disable):
- csvfile="$logdir/Allotment_Connection"
- # Syslog output:
- # 0=No updates;
- # 1=Connectivity changes;
- # 2=Each ping check;
- logger=1
- ############################################
- ### Do not touch ;)
- # Initial Internet state
- inet_state=2
- # Initial `last down` time:
- down_time=--
- # Format date and time for reporting:
- time_format='%H:%M.%S'
- date_format='%d/%m/%Y'
- # Timestamp for log_stamp()
- log_timestamp=$(date +%Y%m%d)
- ############################################
- ### Let's-a go!
- echo -e "\e[30;43m"; clear
- log_stamp () {
- mv "$logfile.log" "$logfile.$log_timestamp.log"
- mv "$csvfile.csv" "$csvfile.$log_timestamp.csv"
- create_output_files
- }
- create_output_files () {
- # Start date for log rotation:
- ldate=$(date +$date_format)
- if [ $logger -ge 1 ]; then logger "$logdir alarm initiated. Parameters: P_IP=$test_ip P_T=${p_tmout} P_D=${p_delay} R_IP=$router_ip F/P=${f_count}/${p_count}"; fi
- # Create the log file with header if it doesn't exist already...
- if [ ! -f "$logfile.log" ]; then
- echo Log created at $ldate > "$logfile.log"
- echo Pinging $test_ip $p_count time\(s\). Looking for $f_count failures... | tee "$logfile.log"
- #nslookup $test_ip
- echo Timeout: ${p_tmout}s - Interval: ${p_delay}s - Fail threshold: ${f_count}/${p_count} | tee -a "$logfile.log"
- else
- echo Appending to main log file : $logfile.log
- fi
- if [ "$csvfile.csv" != "" ]; then
- if [ ! -f "$csvfile.csv" ]; then
- echo Creating CSV output file : $csvfile.csv
- echo \"Date\",\"Time\",\"State\",\"Sent\",\"Replies\",\"Total Time \(ms\)\",\"Avg. Ping \(ms\)\",\"Last change\"> "$csvfile.csv"
- else
- echo Appending CSV output to file : $csvfile.csv
- fi
- fi
- }
- create_output_files
- while true; do
- if [ ! -z $router_ip ] ; then
- router_r=$(ping -W 10 -c $p_count $router_ip | grep "packet loss" || echo $p_count packets transmitted, 0 received, 100% packet loss, time 0ms)
- else
- router_r="0 packets transmitted, 0 received, 0% packet loss, time 0ms"
- fi
- # Clear variables before use:
- fails=
- replies=
- sent=
- # Parse ping command output:
- # Output: 3 packets transmitted, 0 received, 100% packet loss, time 2038ms
- sent=$(echo $router_r | cut -d "," -f 1 | cut -d " " -f 1)
- replies=$(echo $router_r | cut -d "," -f 2 | cut -d " " -f 1-2)
- tottime=$(echo $router_r | cut -d "," -f 4 | cut -d " " -f 3 | cut -d "m" -f 1)
- fails=$(($sent - $replies))
- #echo $timestamp :: Router $router_ip check result: $replies/$sent replies received. $fails requests failed to return.
- if [ $fails -ge $f_count ]; then
- # Display RED window:
- echo -ne "\e[30;41m"
- clear
- tail "$logfile.log"
- # The router is down, or we can't get to the router:
- echo $timestamp :: Router $router_ip is unavailable. $fails\/$sent fails. | tee -a "$logfile.log"
- if [ $logger -ge 1 ]; then logger "$timestamp :: Router $router_ip is unavailable. $fails/$sent fails."; fi
- # Output to csv file, if set:
- if [ "$csvfile.csv" != "" ]; then
- echo $event_date,$event_time,\"Router $router_ip unavailable\",$sent,$(($replies)),0,0,>> "$csvfile.csv"
- fi
- else
- # The router is fine, let's check the Internet:
- # Ping the host <n> times:
- ping_r=$(ping -W $p_tmout -c $p_count $test_ip | grep "packet loss" || echo $p_count packets transmitted, 0 received, 100% packet loss, time 0ms)
- logger $(echo $ping_r | xargs)
- # Clear variables before use:
- fails=
- replies=
- sent=
- # Parse ping command output:
- # Output: 3 packets transmitted, 0 received, 100% packet loss, time 2038ms
- sent=$(echo $ping_r | cut -d "," -f 1 | cut -d " " -f 1)
- replies=$(echo $ping_r | cut -d "," -f 2 | cut -d " " -f 1-2)
- tottime=$(echo $ping_r | cut -d "," -f 4 | cut -d " " -f 3 | cut -d "m" -f 1)
- fails=$(($sent - $replies))
- # Create time string for this pass:
- event_date=$(date +$date_format)
- event_time=$(date +$time_format)
- timestamp="$event_date $event_time"
- # If event date is NOT today, rotate the log files and recreate them:
- if [ "$ldate" != "$event_date" ]; then
- echo Log rotation:
- log_stamp
- log_datestamp=$(date +%Y%m%d)
- fi
- # Detect failure and change in state:
- if [ $fails -ge $f_count ]; then
- # Just started. Connection is DOWN.
- if [ $inet_state -eq 2 ]; then
- # Display RED window:
- echo -ne "\e[30;41m"
- clear
- tail "$logfile.log"
- echo $timestamp :: $logdir is down. $fails\/$sent fails. | tee -a "$logfile.log"
- if [ $logger -ge 1 ]; then logger "$timestamp :: $logdir is down. $fails/$sent fails."; fi
- down_time=$timestamp
- fi
- # Connection was UP. It is now DOWN. Record time.
- if [ $inet_state -eq 1 ]; then
- # Display RED window:
- echo -ne "\e[30;41m"
- clear
- tail "$logfile.log"
- echo $timestamp :: $logdir is now down. $fails\/$sent fails. | tee -a "$logfile.log"
- if [ $logger -ge 1 ]; then logger "$timestamp :: $logdir is now down. $fails/$sent fails."; fi
- down_time=$timestamp
- fi
- # Output to csv file, if set:
- if [ "$csvfile.csv" != "" ]; then
- echo $event_date,$event_time,\"Down\",$sent,$(($replies)),$tottime,$(( ($tottime - (($p_count-1) * 1000)) / ($p_count-1) )),>> "$csvfile.csv"
- fi
- # Output to Syslog via logger, if set:
- if [ $logger -eq 2 ]; then
- logger "$logdir status: DOWN -- $(($replies)) of $sent Successful; Ping time: ${tottime}ms; Avg. Ping time: $(( (${tottime} - ((${p_count} - 1) * 1000)) / (${p_count} - 1) ))ms"
- fi
- inet_state=0
- else
- # Just started. Connection is UP.
- if [ $inet_state -eq 2 ]; then
- # Display GREEN window:
- echo -ne "\e[30;42m"
- clear
- tail "$logfile.log"
- echo $timestamp :: $logdir is up. $fails\/$sent fails. | tee -a "$logfile.log"
- if [ $logger -ge 1 ]; then logger "$timestamp :: $logdir is up. $fails/$sent fails."; fi
- fi
- # Connection was DOWN. It is now UP. Report time.
- if [ $inet_state -eq 0 ]; then
- # Display GREEN window:
- echo -ne "\e[30;42m"
- clear
- tail "$logfile.log"
- echo $timestamp :: $logdir is now up. $fails\/$sent fails. Down since ${down_time}. | tee -a "$logfile.log"
- if [ $logger -ge 1 ]; then logger "$timestamp :: $logdir is now up. $fails/$sent fails. Down since ${down_time}."; fi
- fi
- # Output to csv file, if set:
- if [ "$csvfile.csv" != "" ]; then
- # echo $event_date,$event_time,\"Up\",$sent,$(($replies)),$tottime,$down_time>> "$csvfile.csv"
- echo $event_date,$event_time,\"Up\",$sent,$(($replies)),$tottime,$(( ($tottime - (($p_count-1) * 1000)) / ($p_count-1) )),$down_time>> "$csvfile.csv"
- fi
- # Output to Syslog via logger, if set:
- if [ $logger -eq 2 ]; then logger "$logdir status: UP -- $(($replies)) of $sent Successful; Ping time: ${tottime}ms; Avg. Ping time: $(( (${tottime} - ((${p_count} - 1) * 1000)) / (${p_count} - 1) ))ms; Down since: $down_time"; fi
- inet_state=1
- down_time=--
- fi
- sleep $p_delay
- fi
- done
- ############################################
- ### gEOFf