diff --git a/check-connectivity.sh b/check-connectivity.sh new file mode 100755 index 0000000..de82626 --- /dev/null +++ b/check-connectivity.sh @@ -0,0 +1,479 @@ +#!/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_skipped() { + if $terminal ; then + echo -e "\033[75G[ \033[33m\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 + +} + +# ---------- +# - 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" + +echononl "Load Configurations from file '$(basename "$conf_file")'." +if [[ -f "$conf_file" ]]; then + source "$conf_file" + echo_ok +else + echo_skipped + warn "No configuration file found. Loading script default values.." +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" + + +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 + info 'Machine has at least one interface with physical link is up.' +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 + /sbin/reboot -f + 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 + info "Default IPv4 Gateway(s): ${DEFAULT_GW_4_ARR[@]}" + 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 + info "$msg" + fi +else + echo_failed + PROBLEM_FOUND=true + + error "No default route IPV4is 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 + /sbin/reboot -f + 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 + info "Default IPv6 Gateway(s): ${DEFAULT_GW_6_ARR[@]}" + 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 + info "$msg" + fi + else + echo_failed + + warn "No default route IPv6 is set." + 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 + + info "Found nameserver \033[1m$FIRST_NS\033[m at '/etc/resolv.conf'." +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 + /sbin/reboot -f + fi + else + touch "$RESTART_CHECK_FILE" + fi + clean_up 1 + else + echo_ok + + info "Nameserver works as expected." + fi +else + echo_skipped + warn "Test was not triggert because of nameserver problems.." +fi + + +# --- +# Website reachable? +# --- + +FOUND_CHECK_HOST_PROBLEM=true + +# 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 + error "The web proxy won't let us through" + ;; + + *) echo_failed + error "Something is wrong with HTTP connections. Go check it." + ;; + esac + else + echo_skipped + warn "Test was not triggert because of nameserver problems.." + break + fi + +done + +if $FOUND_CHECK_HOST_PROBLEM ; then + + PROBLEM_FOUND=true + + 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 + /sbin/reboot -f + fi + else + touch "$RESTART_CHECK_FILE" + fi + clean_up 1 +fi + + +! $PROBLEM_FOUND && rm -f "$RESTART_CHECK_FILE" +clean_up 0 diff --git a/conf/check-connectivity.conf.sample b/conf/check-connectivity.conf.sample new file mode 100644 index 0000000..5b8a50f --- /dev/null +++ b/conf/check-connectivity.conf.sample @@ -0,0 +1,33 @@ +# ------------------------------------------- +# - Settings for script check-connectivity.sh +# ------------------------------------------- + +# - IPV6_PRESENT +# - +# - Possible values: true/false +# - +# - Example: +# - IPV6_PRESENT=false +# - +# - Default value: true +# - +#IPV6_PRESENT=true + + +# - DNS_CHECK_HOSTS +# - +# - Blank sepatated list of hostnames checked by lokal nameservice simply +# - for their ip-addresses +# - +# - Defaults to: DNS_CHECK_HOSTS="www.oopen.de www.google.com www.heise.de" +# - +#DNS_CHECK_HOSTS="www.oopen.de www.google.com www.heise.de www.debian.org" + + +# - HTTPS_CHECK_HOSTS +# - +# - Blank sepatated list of websites which will be checked for accessibility +# - +# - Defaults to: HTTPS_CHECK_HOSTS="www.oopen.de www.google.com www.heise.de" +# - +#HTTPS_CHECK_HOSTS="www.oopen.de www.google.com www.heise.de www.debian.org"