#!/usr/bin/env bash script_name="$(basename $(realpath $0))" working_dir="$(dirname $(realpath $0))" conf_file="${working_dir}/conf/${script_name%%.*}.conf" LOCK_DIR="/tmp/$(basename $0).$$.LOCK" log_file="${LOCK_DIR}/${script_name%%.*}.log" PROBLEM_FOUND=false LINK_UP=false RESTART_CHECK_FILE="/tmp/${script_name%%.*}.NEED-RESTART" # ---------- # Base Function(s) # ---------- clean_up() { # Perform program exit housekeeping rm -rf "$LOCK_DIR" blank_line exit $1 } usage() { [[ -n "$1" ]] && error "$1" [[ $terminal ]] && echo -e " \033[1mUsage:\033[m $(basename $0) \033[1mDescription\033[m Script checks presence of some basic network settings and do some basic connectivity tests. If fundamental problems found, then restart machine if this i not the firts time. If this i the first time, file \033[1m$RESTART_CHECK_FILE\033[m is created. \033[1mOptions\033[m No Options present \033[1mFiles\033[m $conf_file: Configuration file \033[1mExample:\033[m Chech connectivity of this machine $(basename $0) " clean_up 1 } echononl(){ if $terminal ; then echo X\\c > /tmp/shprompt$$ if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then echo -e -n " $*\\c" 1>&2 else echo -e -n " $*" 1>&2 fi rm /tmp/shprompt$$ fi } error (){ echo "" if $terminal ; then echo -e " [ \033[31m\033[1mError\033[m ] $*" else echo " [ Error ] $*" fi echo "" } warn (){ echo "" if $terminal ; then echo -e " [ \033[33m\033[1mWarn\033[m ] $*" else echo " [ Warn ] $*" fi echo "" } info (){ if $terminal ; then echo "" echo -e " [ \033[32m\033[1mInfo\033[m ] $*" echo "" fi } echo_ok() { if $terminal ; then echo -e "\033[75G[ \033[32mok\033[m ]" fi } echo_failed(){ if $terminal ; then echo -e "\033[75G[ \033[1;31mfailed\033[m ]" fi } echo_warn() { if $terminal ; then echo -e "\033[75G[ \033[33m\033[1mwarn\033[m ]" fi } echo_skipped() { if $terminal ; then echo -e "\033[75G[ \033[37m\033[1mskipped\033[m ]" fi } trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters echo -n "$var" } blank_line() { if $terminal ; then echo "" fi } # Check if at least one interface has physical link is up # online() { # Call this functionin a subshell to avoid exiting main programm # # Example: # $(online) && echo -e '\033[32m\033[1mOnline\033[m' || echo -e '\033[31m\033[1mOFFLINE\033[m' # find /sys/class/net/ -maxdepth 1 -mindepth 1 \ ! -name "*lo*" \ ! -name "*tun*" \ ! -name "*veth*" \ -exec sh -c 'cat "$0"/carrier 2>&1' {} \; | grep -q -E '^1$' && exit 0 # using ethtool also works: # #-exec sh -c 'ethtool $(basename "$0") 2>&1' {} \; | grep 'ink detected' | grep -i -q 'yes' && exit 0 } reboot_system() { content_type='Content-Type: text/plain;\n charset="utf-8"' datum="$(date +"%d.%m.%Y")" from_address="root@$(hostname --long)" echo -e "To:${ADMIN_EMAIL}\n${content_type}\nSubject:[Connectivity Error] $datum - Reboot System\n$*" | /usr/sbin/sendmail -F "Connectivity Check" -f $from_address $ADMIN_EMAIL sleep 10 /sbin/reboot -f } # ---------- # - Jobhandling # ---------- # - Run 'clean_up' for signals SIGHUP SIGINT SIGTERM # - trap clean_up SIGHUP SIGINT SIGTERM # - Create lock directory '$LOCK_DIR" # mkdir "$LOCK_DIR" # ---------- # - Some checks .. # ---------- # - Running in a terminal? # - if [[ -t 1 ]] ; then terminal=true else terminal=false fi # - Print help? # - if [[ "$(trim $*)" = "-h" ]] || [[ "$(trim $*)" = "--help" ]] ; then usage fi # ========== # - Begin Main Script # ========== # ---------- # - Headline # ---------- if $terminal ; then echo "" echo -e "\033[1m----------\033[m" echo -e "\033[32m\033[1mRunning script \033[m\033[1m$script_name\033[32m .. \033[m" echo -e "\033[1m----------\033[m" echo "" fi # ---------- # Read Configurations from $conf_file # ---------- # - Give your default values here # - DEFAULT_IPV6_PRESENT=true DEFAULT_CHECK_HOSTS="www.oopen.de www.google.de www.heise.de www.debian.org" DEFAULT_ADMIN_EMAIL="argus@oopen.de" echononl "Load Configurations from file '$(basename "$conf_file")'." if [[ -f "$conf_file" ]]; then source "$conf_file" echo_ok else echo_skipped msg="No configuration file found. Script default values where loaded.." if $terminal ; then echo "" echo -e " [ \033[33m\033[1mWarn\033[m ] $msg" echo "" fi #if [[ -z "$msg_warn" ]]; then # msg_warn="$msg" #else # msg_warn="$msg_warn # $msg" #fi fi [[ -z "$IPV6_PRESENT" ]] && IPV6_PRESENT="$DEFAULT_IPV6_PRESENT" [[ -z "$DNS_CHECK_HOSTS" ]] && DNS_CHECK_HOSTS="$DEFAULT_CHECK_HOSTS" [[ -z "$HTTPS_CHECK_HOSTS" ]] && HTTPS_CHECK_HOSTS="$DEFAULT_CHECK_HOSTS" [[ -z "$ADMIN_EMAIL" ]] && ADMIN_EMAIL="$DEFAULT_ADMIN_EMAIL" blank_line echononl "Check if at least one interface has physical link is up" if ! $(online) ; then echo_failed PROBLEM_FOUND=true else echo_ok LINK_UP=true fi if $LINK_UP ; then msg="Machine has at least one interface with physical link is up." if [[ -z "$msg_info" ]]; then msg_info="$msg" else msg_info="$msg_info $msg" fi else error 'Machine is OFFLINE' if [[ -f "$RESTART_CHECK_FILE" ]] ; then _file_mod_time=$(date --utc --reference=$RESTART_CHECK_FILE +%s) _now=$(date +%s) _delta=$(($_now-$_file_mod_time)) echo "_delta=: $_delta" if [[ $_delta -gt 3900 ]] ; then touch "$RESTART_CHECK_FILE" else reboot_system "No interface with physical link is up - Machine is OFFLINE." fi else touch "$RESTART_CHECK_FILE" fi clean_up 1 fi # --- # Routing ok? # --- # Determin IPv4 default gateway(s) # DEFAULT_GW_4="$(/sbin/ip -4 route | awk '/default/ { print $3 }')" if [[ -z "$DEFAULT_GW_4" ]] ; then DEFAULT_GW_4="$(/sbin/ip -4 route | awk '/nexthop/ { print $3 }')" fi declare -a DEFAULT_GW_4_ARR=() for _ip in $DEFAULT_GW_4 ; do DEFAULT_GW_4_ARR+=("$_ip") done echononl "Check if IPv4 default route is set.." if [[ ${#DEFAULT_GW_4_ARR[@]} -gt 0 ]] ; then echo_ok if [[ ${#DEFAULT_GW_4_ARR[@]} -eq 1 ]] ; then msg="Default IPv4 Gateway(s): ${DEFAULT_GW_4_ARR[@]}" if [[ -z "$msg_info" ]]; then msg_info="$msg" else msg_info="$msg_info $msg" fi else msg="Default IPv4 Gateway(s): ${DEFAULT_GW_4_ARR[0]}" for index in "${!DEFAULT_GW_4_ARR[@]}"; do [[ $index -eq 0 ]] && continue msg="$msg ${DEFAULT_GW_4_ARR[$index]}" done if [[ -z "$msg_info" ]]; then msg_info="$msg" else msg_info="$msg_info $msg" fi fi else echo_failed PROBLEM_FOUND=true error "No default route IPV4 is set." if [[ -f "$RESTART_CHECK_FILE" ]] ; then _file_mod_time=$(date --utc --reference=$RESTART_CHECK_FILE +%s) _now=$(date +%s) _delta=$(($_now-$_file_mod_time)) echo "_delta=: $_delta" if [[ $_delta -gt 3900 ]] ; then touch "$RESTART_CHECK_FILE" else reboot_system "No default route IPv4 is set." fi else touch "$RESTART_CHECK_FILE" fi clean_up 1 fi # Determin IPv6 default gateway(s) # if $IPV6_PRESENT ; then DEFAULT_GW_6="$(/sbin/ip -6 route | awk '/default/ { print $3 }')" declare -a DEFAULT_GW_6_ARR=() for _ip in $DEFAULT_GW_6 ; do DEFAULT_GW_6_ARR+=("$_ip") done echononl "Check if IPv6 default route is set.." if [[ ${#DEFAULT_GW_6_ARR[@]} -gt 0 ]] ; then echo_ok if [[ ${#DEFAULT_GW_6_ARR[@]} -eq 1 ]] ; then msg="Default IPv6 Gateway(s): ${DEFAULT_GW_6_ARR[@]}" if [[ -z "$msg_info" ]]; then msg_info="$msg" else msg_info="$msg_info $msg" fi else msg="Default IPv6 Gateway(s): ${DEFAULT_GW_6_ARR[0]}" for index in "${!DEFAULT_GW_6_ARR[@]}"; do [[ $index -eq 0 ]] && continue msg="$msg ${DEFAULT_GW_6_ARR[$index]}" done if [[ -z "$msg_info" ]]; then msg_info="$msg" else msg_info="$msg_info $msg" fi fi else echo_warn msg="No default route IPv6 is set." if [[ -z "$msg_warn" ]]; then msg_warn="$msg" else msg_warn="$msg_warn $msg" fi fi fi # --- # Nameservice ok? # --- FOUND_NS_PROBLEM=true # Check if nameserver entry at /etc/resolv.conf ist present # echononl "Check if nameserver entry at /etc/resolv.conf ist present.." FIRST_NS="$(cat /etc/resolv.conf | awk '/^nameserver/ {print $2}' | awk 'NR == 1 {print; exit}')" if [[ -n "$FIRST_NS" ]] ; then echo_ok FOUND_NS_PROBLEM=false msg="Found nameserver \033[1m$FIRST_NS\033[m at '/etc/resolv.conf'." if [[ -z "$msg_info" ]]; then msg_info="$msg" else msg_info="$msg_info $msg" fi else echo_failed error "No nameserverentry at '/etc/resolv.conf' found." fi # Check if nameservice works.. # echononl "Check if first nameserver works.." if ! $FOUND_NS_PROBLEM ; then FOUND_NS_PROBLEM=true for _hostname in $DNS_CHECK_HOSTS ; do if [[ -n "$(dig +short @$FIRST_NS $_hostname)" ]] ; then FOUND_NS_PROBLEM=false break fi done if $FOUND_NS_PROBLEM ; then echo_failed PROBLEM_FOUND=true error "First nameserver located at /etc/resolv.conf does not work properly." if [[ -f "$RESTART_CHECK_FILE" ]] ; then _file_mod_time=$(date --utc --reference=$RESTART_CHECK_FILE +%s) _now=$(date +%s) _delta=$(($_now-$_file_mod_time)) echo "_delta=: $_delta" if [[ $_delta -gt 3900 ]] ; then touch "$RESTART_CHECK_FILE" else reboot_system "First nameserver located at /etc/resolv.conf does not work properly." fi else touch "$RESTART_CHECK_FILE" fi clean_up 1 else echo_ok msg="Nameserver works as expected." if [[ -z "$msg_info" ]]; then msg_info="$msg" else msg_info="$msg_info $msg" fi fi else echo_skipped msg="Resolver test was not triggert because of nameserver problems.." if [[ -z "$msg_warn" ]]; then msg_warn="$msg" else msg_warn="$msg_warn $msg" fi fi # --- # Website reachable? # --- if ! $FOUND_NS_PROBLEM ; then FOUND_CHECK_HOST_PROBLEM=true else FOUND_CHECK_HOST_PROBLEM=false fi # Check if some websites reachable.. # for _host in $HTTPS_CHECK_HOSTS ; do echononl "Check if website \033[1m$_host\033[m is reachable.." if ! $FOUND_NS_PROBLEM ; then case "$(curl -s --max-time 2 -I $_host | sed 's/^[^ ]* *\([0-9]\).*/\1/; 1q')" in [23]) echo_ok FOUND_CHECK_HOST_PROBLEM=false break ;; 5) echo_failed ;; *) echo_failed ;; esac else echo_skipped msg="Website accessibility test was not triggert because of nameserver problems.." if [[ -z "$msg_warn" ]]; then msg_warn="$msg" else msg_warn="$msg_warn $msg" fi break fi done if $FOUND_CHECK_HOST_PROBLEM ; then PROBLEM_FOUND=true error "No (configured) website could be reached." if [[ -f "$RESTART_CHECK_FILE" ]] ; then _file_mod_time=$(date --utc --reference=$RESTART_CHECK_FILE +%s) _now=$(date +%s) _delta=$(($_now-$_file_mod_time)) echo "_delta=: $_delta" if [[ $_delta -gt 3900 ]] ; then touch "$RESTART_CHECK_FILE" else reboot_system "No website could be reached." fi else touch "$RESTART_CHECK_FILE" fi clean_up 1 else if ! $FOUND_NS_PROBLEM ; then msg="Extern Websites are reachable." if [[ -z "$msg_info" ]]; then msg_info="$msg" else msg_info="$msg_info $msg" fi fi fi if [[ -n "$msg_info" ]]; then info "$msg_info" fi if [[ -n "$msg_warn" ]]; then warn "$msg_warn" fi ! $PROBLEM_FOUND && rm -f "$RESTART_CHECK_FILE" clean_up 0