#!/usr/bin/env bash ## -------------------------- ## --- Make your changes here ## -------------------------- LOGGING_CONSOLE=false DEBUG=false log_file=/var/log/check_dsl.log ## - Put in your DSL devices (refers to your network configuration) ## - youe wish be congigured by that script ## - DSL_DEVICES="ppp-surf2 ppp-surf1 ppp-st" admin_email=root from_address="check-dsl@`hostname -f`" company="Gemeinschaft Altenschlirf" content_type='Content-Type: text/plain;\n charset="utf-8"' ########################################## ## --- Dont't make changes after this line ########################################## ## ------------------ ## --- Some functions ## ------------------ ## - Check if a given array (parameter 2) contains a given string (parameter 1) ## - containsElement () { local e for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done return 1 } ## ------------------------------------------------- ## --- If script is already running, stop execution ## ------------------------------------------------- LOCK_DIR=/tmp/`basename $0`.LOCK if mkdir "$LOCK_DIR" 2> /dev/null ; then ## - Remove lockdir when the script finishes, or when it receives a signal trap 'rm -rf "$LOCK_DIR"' 0 2 15 else datum=`date +"%d.%m.%Y"` msg="[ Error ]: A previos instance of script \"`basename $0`\" seems already be running.\n\n Exiting now.." echo -e "To:${admin_email}\n${content_type}\nSubject:DSL Script Error $company -- $datum\n\n${msg}\n" | /usr/sbin/sendmail -F "DSL Monitoring $company" -f $from_address $admin_email if $LOGGING_CONSOLE ; then echo "" echo "[ Error ]: A previos instance script \"`basename $0`\" seems already be running." echo "" echo " Exiting now.." echo "" fi exit 1 fi ## - Define (non associative) array ## - declare -a dsl_devices_arr for _dsl_device in $DSL_DEVICES ; do dsl_devices_arr+=("$_dsl_device") done declare -a online_devices_arr for _online_device in "$@" ; do online_devices_arr+=("$_online_device") done ## - Define associative array ## - declare -A remote_gw_arr declare -A filetime_PID_arr for dsl_device in "${online_devices_arr[@]}" ; do remote_gw_address=`ifconfig $dsl_device 2> /dev/null | grep "inet Adresse" | cut -d":" -f3 | cut -d" " -f1` remote_gw_arr[$dsl_device]=$remote_gw_address _pid_file=/var/run/${dsl_device}.pid if [ -f $_pid_file ]; then filetime_PID_arr[$dsl_device]=`stat -c %Y /var/run/${dsl_device}.pid` else filetime_PID_arr[$dsl_device]="NOT FOUND" fi done ping_test_hosts="oopen.de google.com heise.de debian.org ubuntu.com" declare -a ping_ip_arr; #for _key in "${!filetime_PID_arr[@]}" ; do # echo "filetime_PID_arr[$_key]: ${filetime_PID_arr[$_key]}" #done #for _key in "${!remote_gw_arr[@]}" ; do # echo "remote_gw_arr[$_key]: ${remote_gw_arr[$_key]}" #done #for _device in ${online_devices_arr[@]} ; do # echo "$_device" #done echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] ## ---" >> $log_file echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] ## --- Starting script `basename $0`" >> $log_file echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] ## --- Devices Online...: ${online_devices_arr[@]}" >> $log_file echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] ## --- Remote Gateways..: ${remote_gw_arr[@]}" >> $log_file echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] ## ---" >> $log_file while true ; do changed=false for dsl_device in "${dsl_devices_arr[@]}" ; do if $DEBUG ; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] ## --- Device $dsl_device " >> $log_file fi remote_gw_address=`ifconfig $dsl_device 2> /dev/null | grep "inet Adresse" | cut -d":" -f3 | cut -d" " -f1` iface_name="dsl-`echo $dsl_device | cut -d '-' -f2`" rt_name="dsl_`echo $dsl_device | cut -d '-' -f2`" if [ -z "$remote_gw_address" ]; then if containsElement "$dsl_device" ${online_devices_arr[@]} ; then ## - ## - ## - online offline echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Status Devices \"$dsl_device\" changed" >> $log_file echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Devices \"$dsl_device\" is now OFFLINE" >> $log_file if ps -x | grep -E "/usr/sbin/pppd\s+call\s+$iface_name" > /dev/null 2>&1 ; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] pppd for \"$iface_name\" is running: Waiting another period" >> $log_file else echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Trying to start pppd for \"$dsl_device\".." >> $log_file /usr/sbin/pppd call $iface_name > /dev/null 2>&1 fi ## - Remove device from array online_devices_arr ## - for _index in ${!online_devices_arr[@]} ; do if [ "${online_devices_arr[$_index]}" = "$dsl_device" ]; then unset online_devices_arr[$_index] break fi done ## - Also remove device from remote_gw_arr ## - unset remote_gw_arr[$dsl_device] changed=true else ## - ## - ## - offline offline if $DEBUG ; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] $dsl_device is still offline" >> $log_file fi if ps -x | grep -E "/usr/sbin/pppd\s+call\s+$iface_name" > /dev/null 2>&1 ; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] pppd for \"$iface_name\" is running: Waiting another period" >> $log_file else echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Trying to start pppd for \"$dsl_device\".." >> $log_file /usr/sbin/pppd call $iface_name > /dev/null 2>&1 fi fi else if containsElement "$dsl_device" ${online_devices_arr[@]} ; then ## - ## - ## - online online if $DEBUG ; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] $dsl_device is still online" >> $log_file fi ## - Check if remote gateway has changed ## - if [ "$remote_gw_address" != "${remote_gw_arr[$dsl_device]}" ]; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Remote Gateway on device \"$dsl_device\" has changed: ${remote_gw_arr[$dsl_device]} --> $remote_gw_address" >> $log_file remote_gw_arr[$dsl_device]=$remote_gw_address filetime_PID_arr[$dsl_device]=`stat -c %Y /var/run/${dsl_device}.pid` changed=true else if $DEBUG ; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] Remote Gateway on device \"$dsl_device\": still ${remote_gw_arr[$dsl_device]}" >> $log_file fi ## - Test if pid-file's modify time hs changed ## - ## - Notice: that happens if your provider forces a reconnect (mostly one time a day ## - or in other words after 1440 minutes) ## - _pid_file=/var/run/${dsl_device}.pid if [ -f $_pid_file ]; then if [ "`stat -c %Y $_pid_file`" != "${filetime_PID_arr[$dsl_device]}" ]; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Modify time for pid-file \"${dsl_device}.pid\" has changed" >> $log_file filetime_PID_arr[$dsl_device]=`stat -c %Y $_pid_file` changed=true else ## - Check if routing through this dsl connection realy works ## - failed=true if [ ${#ping_ip_arr[@]} -lt 1 ]; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] No ip-address for ping-test is set. Skipping test.." >> $log_file else for _key in ${!ping_ip_arr[@]} ; do /sbin/ip rule add to ${ping_ip_arr[$_key]} table $rt_name if ping -q -c2 ${ping_ip_arr[$_key]} >/dev/null 2>&1 ; then if $DEBUG ; then _local_gw=`curl -4 https://meine-ip.oopen.de 2> /dev/null` if [ -n "$_local_gw" ]; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] Using local gateway \"$_local_gw\" for ping test" >> $log_file fi echo "`date +'%Y-%m-%d %H:%M:%S'` [ Debug ] Ping test (to ${ping_ip_arr[$_key]}) for device \"${dsl_device}\" was successful." >> $log_file fi /sbin/ip rule del to ${ping_ip_arr[$_key]} table $rt_name failed=false break fi /sbin/ip rule del to ${ping_ip_arr[$_key]} table $rt_name done if $failed ; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Ping test for device \"${dsl_device}\" failed" >> $log_file i echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Status Devices \"$dsl_device\" changed" >> $log_file echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Devices \"$dsl_device\" is now OFFLINE" >> $log_file _pid=`ps -ax | grep -e "pppd call $iface_name" | grep -v grep | awk '{print$1}'` echo "`date +'%Y-%m-%d %H:%M:%S'` [ Info ] Kill ppp-daemon for $iface_name (pid $_pid)" >> $log_file ## - Remove device from array online_devices_arr ## - for _index in ${!online_devices_arr[@]} ; do if [ "${online_devices_arr[$_index]}" = "$dsl_device" ]; then unset online_devices_arr[$_index] break fi done ## - Also remove device from remote_gw_arr ## - unset remote_gw_arr[$dsl_device] kill -9 $_pid changed=true fi fi fi else filetime_PID_arr[$dsl_device]="NOT FOUND" echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] No pid-file for connection \"${dsl_device}\"found" >> $log_file changed=true fi fi else ## - ## - ## - offline online echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Status Devices \"$dsl_device\" changed" >> $log_file echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Devices \"$dsl_device\" is now online" >> $log_file ## - Add device to array online_devices_arr ## - online_devices_arr+=("$dsl_device") remote_gw_arr[$dsl_device]=$remote_gw_address filetime_PID_arr[$dsl_device]=`stat -c %Y /var/run/${dsl_device}.pid` changed=true fi fi done if $changed ; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Status Online Devices changed" >> $log_file echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Online Devices: ${online_devices_arr[@]}" >> $log_file echo "`date +'%Y-%m-%d %H:%M:%S'` [ Warn ] Reconfigure Routing: invoking script \"netconfig_dsl.sh\".." >> $log_file /root/bin/netconfig_dsl.sh > /dev/null 2>&1 #/root/bin/netconfig_dsl_round-robin.sh > /dev/null 2>&1 datum=`date +"%d.%m.%Y"` msg="[ `date +\"%H:%M:%S\"` ]: Status Online Devices changed..\n Online Devices: ${online_devices_arr[@]}\n\n Script \"netconfig_dsl.sh\" was invoked to reconfigure routing." echo -e "To:${admin_email}\n${content_type}\nSubject:DSL Status changed $company -- $datum\n\n${msg}\n" | /usr/sbin/sendmail -F "DSL Monitoring $company" -f $from_address $admin_email fi ## - Set IP-adresses for Ping-Test at next run ## - if [ ${#online_devices_arr[@]} -gt 0 ]; then ping_test_ip="" unset ping_ip_arr declare -i i=0 for _host in $ping_test_hosts ; do while [ $i -lt 2 ]; do ping_test_ip=`dig +short $_host | head -1` if ping -q -c2 $ping_test_ip >/dev/null 2>&1 ; then ping_ip_arr+=("$ping_test_ip") let i++ break fi done done if [ ${#ping_ip_arr[@]} -lt 1 ]; then echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] No ip-address for ping test found " >> $log_file echo "`date +'%Y-%m-%d %H:%M:%S'` [ Error ] Looked for IP-Addresses at hosts: $ping_test_hosts" >> $log_file fi fi sleep 30 done exit 0