diff --git a/.gitignore b/.gitignore index 12b01d2..8356ed2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ *.swp /conf/*.conf -/conf/*.conf.* +/conf/*.conf /BAK/* diff --git a/check_cert_for_dovecot.sh b/check_cert_for_dovecot.sh index 5673e18..3ec84f6 100755 --- a/check_cert_for_dovecot.sh +++ b/check_cert_for_dovecot.sh @@ -227,7 +227,7 @@ systemd_supported=false systemd=$(which systemd) systemctl=$(which systemctl) -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_cert_for_keycloak.sh b/check_cert_for_keycloak.sh new file mode 100755 index 0000000..51b2520 --- /dev/null +++ b/check_cert_for_keycloak.sh @@ -0,0 +1,426 @@ +#!/usr/bin/env bash + +# =============================================================== +# - Don't make definitions here! Do this at the configuration file +# ================================================================ + +script_name="$(basename $(realpath $0))" +working_dir="$(dirname $(realpath $0))" + +conf_file="${working_dir}/conf/${script_name%%.*}.conf" + +# ---------- +# - +# - Script checks, whether the certificate for mumble services are up to date. If +# - newer versions than the installed one found, script changes the installed +# - key/cert to the latest version. +# - +# - Note !! +# - This script is very special to the server environment of machine 'o13-il.oopen.de' +# - +# ---------- + +LOCK_DIR="/tmp/${script_name%%.*}.LOCK" +log_file="${LOCK_DIR}/${script_name%%.*}.log" + +restart_service=false + + +# ------------- +# --- Some functions +# ------------- + +clean_up() { + + # Perform program exit housekeeping + rm -rf "$LOCK_DIR" + exit $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 +} + +fatal(){ + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mFatal\033[m ]: $*" + echo "" + echo -e " \033[31m\033[1mScript was interupted\033[m!" + else + echo " [ Fatal ]: $*" + echo "" + echo " Script was terminated...." + fi + echo "" + clean_up 1 +} + +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[1mWarning\033[m ]: $*" + else + echo " [ Warning ]: $*" + fi + echo "" +} + +info() { + if $terminal ; then + echo "" + echo -e " [ \033[32m\033[1mInfo\033[m ]: $*" + echo "" + 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 +} + + +echo_done() { + if $terminal ; then + echo -e "\033[75G[ \033[32mok\033[m ]" + fi +} + +blank_line() { + if $terminal ; then + echo "" + fi +} + + +# ------------- +# - Job is already running? +# ------------- + +# - If job already runs, stop execution.. +# - +if mkdir "$LOCK_DIR" 2> /dev/null ; then + + # - Remove lockdir when the script finishes, or when it receives a signal + # - + trap clean_up SIGHUP SIGINT SIGTERM + +else + + msg="A previos instance of script \"`basename $0`\" seems already be running." + + echo "" + if $terminal ; then + echo -e "[ \033[31m\033[1mFatal\033[m ]: $msg" + echo "" + echo -e " \033[31m\033[1mScript was interupted\033[m!" + else + echo " [ Fatal ]: $msg" + echo "" + echo " Script was interupted!" + fi + echo + + exit 1 + +fi + + +# ------------- +# --- Some checks +# ------------- + +# - Running in a terminal? +# - +if [[ -t 1 ]] ; then + terminal=true +else + terminal=false +fi + + +# - Read Configurations from $conf_file +# - +if [[ ! -f "$conf_file" ]]; then + fatal " Configuration file '$(basename ${conf_file})' not found!" +else + source $conf_file +fi + +[[ -z "$service_domain" ]] && fatal " Parameter 'service_domain' not set but is reqired!" + +[[ -z "$cert_installed" ]] && cert_installed="/opt/keycloak/certs/${service_domain}.crt" +[[ -z "$cert_newest" ]] && cert_newest="/var/lib/dehydrated/certs/${service_domain}/fullchain.pem" +[[ -z "$key_installed" ]] && key_installed="/opt/keycloak/certs/${service_domain}.key" +[[ -z "$key_newest" ]] && key_newest="/var/lib/dehydrated/certs/${service_domain}/privkey.pem" + +[[ -z "$service_name" ]] && service_name="Keycloak" +[[ -z "$check_string_ps" ]] && check_string_ps="[[:digit:]]\ lua[[:digit:]].[[:digit:]] /usr/bin/prosody" +[[ -z "$service_user" ]] && service_user="keycloak" +[[ -z "$service_group" ]] && service_group="keycloak" + +# - Systemd supported ? +# - +systemd_supported=false +systemd=$(which systemd) +systemctl=$(which systemctl) + +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then + systemd_supported=true +fi + +SYSTEMD_SERVICE= + +if systemctl -t service list-unit-files \ + | grep -e "^${service_name,,}d" \ + | grep -q -E "(enabled|disabled|generated)" 2> /devnull ; then + + SYSTEMD_SERVICE="$(systemctl -t service list-unit-files | grep -e "^${service_name,,}d" | awk '{print$1}' | head -1)" +elif systemctl -t service list-unit-files \ + | grep -e "^${service_name,,}-server" \ + | grep -q -E "(enabled|disabled|generated)" 2> /devnull ; then + + SYSTEMD_SERVICE="$(systemctl -t service list-unit-files | grep -e "^${service_name,,}-server" | awk '{print$1}' | head -1)" +elif systemctl -t service list-unit-files \ + | grep -e "^${service_name,,}" \ + | grep -q -E "(enabled|disabled|generated)" 2> /devnull ; then + + SYSTEMD_SERVICE="$(systemctl -t service list-unit-files | grep -e "^${service_name,,}" | awk '{print$1}' | head -1)" +fi + + +if [[ -z "$SYSTEMD_SERVICE" ]] ; then + fatal "No service file for $service_name found!" +fi + + +# ------------- +# - Don't run script, if any give path for cert/key does not exists +# ------------- + +if [[ ! -f "$cert_newest" ]] ; then + fatal "Newest Certificate '$cert_newest' for service '${service_name}' not found!" +elif [[ ! -f "$key_newest" ]] ; then + fatal "Newest Key '$key_newest' for service '${service_name}' not found!" +fi + +blank_line +echononl " Create Cert/Key Directory '$(dirname "$cert_installed")'.." +if [[ ! -d "$(dirname "$cert_installed")" ]] ; then + mkdir -p "$(dirname "$cert_installed")" > $log_file 2>&1 + if [[ $? -eq 0 ]] ; then + echo_done + + echononl " Change Permissions for Cert/Key Directory '$(dirname "$cert_installed")'.." + chmod 755 "$(dirname "$cert_installed")" > $log_file 2>&1 + if [[ $? -eq 0 ]] ; then + echo_done + else + echo_failed + error "$(cat "$log_file")" + fi + + else + echo_failed + error "$(cat "$log_file")" + fi +else + echo_skipped +fi + + +# ------------- +# - Check if key/cert are up to date, change them if needed. +# ------------- + +if ! diff "$(realpath "$cert_installed")" "$(realpath "$cert_newest")" > /dev/null 2>&1 ; then + + _failed=false + + warn "Certificate for service '${service_name}' is outdated! + + Try to update certificate and key.." + + echononl " Update certificat for for service '${service_name}' .." + > $log_file + if [[ -h "$cert_installed" ]] ; then + if [[ "$(dirname "$cert_installed")" = "$(dirname "$(realpath "$cert_installed")")" ]]; then + rm "$(realpath "$cert_installed")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + fi + fi + + rm -f "$cert_installed" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + cp -a "$(realpath "$cert_newest")" "$(dirname "$cert_installed")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + chown ${service_user}:$service_group "$(dirname "$cert_installed")/$(basename "$(realpath "$cert_newest")")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + ln -s "$(basename "$(realpath "$cert_newest")")" "$cert_installed" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + if $_failed ; then + echo_failed + error "$(cat "$log_file")" + else + echo_done + fi + + if ! $_failed ; then + + _failed=false + + echononl " Update key for service '${service_name}' .." + if [[ -h "$key_installed" ]] ; then + if [[ "$(dirname "$key_installed")" = "$(dirname "$(realpath "$key_installed")")" ]]; then + rm "$(realpath "$key_installed")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + fi + fi + + rm -f "$key_installed" > $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + cp -a "$(realpath "$key_newest")" "$(dirname "$key_installed")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + chown ${service_user}:$service_group "$(dirname "$key_installed")/$(basename "$(realpath "$key_newest")")" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + ln -s "$(basename "$(realpath "$key_newest")")" "$key_installed" >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + + if $_failed ; then + echo_failed + error "$(cat "$log_file")" + else + echo_done + restart_service=true + fi + + fi + + if ! $_failed ; then + if $terminal ; then + info "Certificate/Key for service '${service_name}' is now up to date" + else + echo "" + echo " [ Info ]: Certificate/Key for service '${service_name}' is now up to date" + echo "" + fi + else + error "Updating Certificate/Key for service '${service_name}' failed!" + fi + +else + up_to_date=true + info "Certificate for service '${service_name}' is up to date!" +fi + +if $restart_service ; then + + _failed=false + echononl "Going to restart Service '${service_name}' .." + $systemctl daemon-reload > $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + sleep 2 + + $systemctl stop $SYSTEMD_SERVICE >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + sleep 10 + + $systemctl start $SYSTEMD_SERVICE >> $log_file 2>&1 + if [[ $? -ne 0 ]]; then + _failed=true + fi + if $_failed ; then + echo_failed + error "$($log_file)" + else + echo_done + fi + + if ! $_failed ; then + + _failed=false + declare -i counter=0 + while ! $(systemctl is-active --quiet ${SYSTEMD_SERVICE}) ; do + if [[ $counter -gt 10 ]]; then + _failed=true + break + else + ((counter++)) + fi + sleep 1 + done + + fi + + if $_failed ; then + error "Restarting service '${service_name}' failed!" + else + if $terminal ; then + info "'${service_name}' Service was restarted. the new pid is '$PID'." + else + echo "" + echo " '${service_name}' Service was restarted. the new pid is '$PID'." + echo "" + fi + fi + +fi + +clean_up 0 + diff --git a/check_cert_for_prosody.sh b/check_cert_for_prosody.sh index e7e979b..be8fb64 100755 --- a/check_cert_for_prosody.sh +++ b/check_cert_for_prosody.sh @@ -177,7 +177,7 @@ systemd_supported=false systemd=$(which systemd) systemctl=$(which systemctl) -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_cert_for_service.sh b/check_cert_for_service.sh index 11f9dc0..7425286 100755 --- a/check_cert_for_service.sh +++ b/check_cert_for_service.sh @@ -7,22 +7,6 @@ working_dir="$(dirname $(realpath $0))" conf_file="${working_dir}/conf/check_cert_for_service.conf" -# ---------- -# - -# - Script checks, whether the certificate for mumble services are up to date. If -# - newer versions than the installed one found, script changes the installed -# - key/cert to the latest version. -# - -# - Note !! -# - This script is very special to the server environment of machine 'o13-il.oopen.de' -# - -# ---------- - -LOCK_DIR="/tmp/check_cert_${service_name}.sh.LOCK" -log_file="${LOCK_DIR}/check_cert_${service_name}.log" - -restart_service=false - # ------------- # --- Some functions @@ -103,10 +87,27 @@ echo_done() { } +restart_service=false + + +# -------------- +# - Read Configurations from $conf_file +# -------------- + +if [[ ! -f "$conf_file" ]]; then + fatal " Configuration file '$(basename ${conf_file})' not found!" +else + source $conf_file +fi + + # ------------- # - Job is already running? # ------------- +LOCK_DIR="/tmp/check_cert_${service_name}.sh.LOCK" +log_file="${LOCK_DIR}/check_cert_${service_name}.log" + # - If job already runs, stop execution.. # - if mkdir "$LOCK_DIR" 2> /dev/null ; then @@ -148,29 +149,7 @@ else terminal=false fi - -# - Read Configurations from $conf_file -# - -if [[ ! -f "$conf_file" ]]; then - fatal " Configuration file '$(basename ${conf_file})' not found!" -else - source $conf_file -fi - -# - Systemd supported ? -# - -systemd_supported=false -systemd=$(which systemd) -systemctl=$(which systemctl) - -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then - systemd_supported=true -fi - -SYSTEMD_SERVICE= -SYSV_INIT_SCRIPT= - -if $systemd_supported ; then +if [[ -n "=$(which systemctl)" ]] ; then if systemctl -t service list-unit-files \ | grep -e "^${service_name,,}d" \ | grep -q -E "(enabled|disabled|generated)" 2> /devnull ; then @@ -336,19 +315,19 @@ if $restart_service ; then _failed=false echononl "Going to restart Service '${service_name}' .." if [[ -n "$SYSTEMD_SERVICE" ]] ; then - $systemctl daemon-reload > $log_file 2>&1 + systemctl daemon-reload > $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi sleep 2 - $systemctl stop $SYSTEMD_SERVICE >> $log_file 2>&1 + systemctl stop $SYSTEMD_SERVICE >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi sleep 10 - $systemctl start $SYSTEMD_SERVICE >> $log_file 2>&1 + systemctl start $SYSTEMD_SERVICE >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi diff --git a/check_clamav-services.sh b/check_clamav-services.sh index 149272e..8392643 100755 --- a/check_clamav-services.sh +++ b/check_clamav-services.sh @@ -89,9 +89,10 @@ fi # - Is this a systemd system? # - -if [[ "X`which systemd`" = "X" ]]; then - systemd_exists=false -else +systemd=$(which systemd) +systemctl=$(which systemctl) + +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_exists=true fi diff --git a/check_clamavd.sh b/check_clamavd.sh index 64387a7..152aec6 100755 --- a/check_clamavd.sh +++ b/check_clamavd.sh @@ -134,7 +134,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_confluence.sh b/check_confluence.sh index 919c299..4631c84 100755 --- a/check_confluence.sh +++ b/check_confluence.sh @@ -116,7 +116,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_coolwsd_service.sh b/check_coolwsd_service.sh new file mode 100755 index 0000000..259ccc6 --- /dev/null +++ b/check_coolwsd_service.sh @@ -0,0 +1,332 @@ +#!/usr/bin/env bash + +LOCK_DIR="/tmp/$(basename $0).$$.LOCK" +log_file="${LOCK_DIR}/${script_name%%.*}.log" + +CONFLICTING_SCRIPTS="check_sympa_spool_msg_dir.sh" + + +#--------------------------------------- +#----------------------------- +# Base Function(s) +#----------------------------- +#--------------------------------------- + +usage() { + + + [[ -n "$1" ]] && error "$1" + + + [[ $terminal ]] && echo -e " +\033[1mUsage:\033[m + + $(basename $0) + +\033[1mDescription\033[m + + Script checks if given service is running and tries to restart service + if it is not running. + +\033[1mOptions\033[m + + No Options available + +\033[1mExample:\033[m + + Check if apache2 service is runnin. Restart service if needed. + + $(basename $0) apache2 + +" + + clean_up 1 +} + + +clean_up() { + + # Perform program exit housekeeping + rm -rf "$LOCK_DIR" + blank_line + exit $1 +} + + +fatal(){ + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mFatal\033[m ] $*" + else + echo -e " [ Fatal ] $*" + fi + echo "" + if $terminal ; then + echo -e " \033[1mScript terminated\033[m.." + else + echo -e " Script terminated.." + fi + clean_up 1 +} + +error (){ + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mError\033[m ] $*" + else + echo " [ Error ] $*" + fi + echo "" +} + +warn (){ + if $LOGGING || $terminal ; then + echo "" + if $terminal ; then + echo -e " [ \033[33m\033[1mWarn\033[m ] $*" + else + echo " [ Warn ] $*" + fi + echo "" + fi +} + +info (){ + if $LOGGING || $terminal ; then + echo "" + if $terminal ; then + echo -e " [ \033[32m\033[1mInfo\033[m ] $*" + else + echo " [ Info ] $*" + fi + echo "" + fi +} + +ok (){ + if $LOGGING || $terminal ; then + echo "" + if $terminal ; then + echo -e " [ \033[32m\033[1mOk\033[m ] $*" + else + echo " [ Ok ] $*" + fi + echo "" + fi +} + +warn_only_terminal () { + if $terminal ; then + echo "" + echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*" + echo "" + fi +} + +blank_line() { + if $terminal ; then + echo "" + fi +} + +trim() { + local var="$*" + var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters + var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters + echo -n "$var" +} + +# - Running in a terminal? +# - +if [[ -t 1 ]] ; then + terminal=true + LOGGING=true +else + terminal=false + LOGGING=false +fi + + +# ---------- +# - Jobhandling +# ---------- + +# - Run 'clean_up' for signals SIGHUP SIGINT SIGTERM +# - +trap clean_up SIGHUP SIGINT SIGTERM + +# - Create lock directory '$LOCK_DIR" +# +mkdir "$LOCK_DIR" + + +# - Stop here, if these give scripts are running +# - +if [[ ${#CONFLICTING_SCRIPTS} -gt 0 ]] ; then + + # - Try using a random start delay to prevent (or at least have a small chance) that + # - conflicting scripts will both/all abort if they start at the same time. + # - + # - !! Notice !! + # - This only makes sense if a fixed LOCK directory is used, otherwise the process list + # - (and NOT the LOCK-directory) is used to look for scripts running in parallel. + # - + # - Skip delay if running in an terminal (from copnsole) + # - + if ! $terminal ; then + if [[ "$LOCK_DIR" = "/tmp/${script_name%%.*}.LOCK" ]]; then + _shift="$(( $RANDOM % 10 + 1 ))" + sleep $(( $RANDOM % 25 + $_shift )) + fi + fi + + _stop_running=false + for _val in $CONFLICTING_SCRIPTS ; do + + IFS=':' read -a _val_arr <<< "${_val}" + + _script_name="$(basename ${_val_arr[0]})" + + if [[ -n "${_val_arr[1]}" ]] ; then + + if [[ "${_val_arr[1]}" = "CHECK_PROCESS_LIST" ]] ; then + + check_string_ps="${_val_arr[0]}" + if ps -e f | grep -E "\s+${check_string_ps}" | grep -v grep | grep -v -E "\s+vim\s+" > /dev/null ; then + _stop_running=true + fi + + elif [[ -d "${_val_arr[1]}" ]] ; then + _stop_running=true + fi + + elif [[ -d "/tmp/${_script_name%%.*}.LOCK" ]]; then + _stop_running=true + fi + + if $_stop_running ; then + + warn_only_terminal "\033[1m${_script_name}\033[m is currently running, but it conflicts with this script. + + Exiting now.." + + clean_up 1 + + fi # if $_stop_running ; then + + done # for _val in $CONFLICTING_SCRIPTS ; do + +fi # if [[ ${#CONFLICTING_SCRIPTS} -gt 0 ]] ; then + + + +#--------------------------------------- +#----------------------------- +# Check some prerequisites +#----------------------------- +#--------------------------------------- + + +SYSTEMD_SERVICE="${1:-coolwsd}" + + +# - Systemd supported ? +# - +systemd=$(which systemd) +systemctl=$(which systemctl) + +systemd_supported=false +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then + systemd_supported=true +else + fatal "Systemd is not present!" +fi + +if ! systemctl list-unit-files --type=service | grep -q "^${SYSTEMD_SERVICE}\.service"; then + fatal "Service '${SYSTEMD_SERVICE}' not present!" + clean_up 2 +fi + + +#--------------------------------------- +#----------------------------- +# Check if service is running +#----------------------------- +#--------------------------------------- + +if $LOGGING ; then + declare -i _length="${#SYSTEMD_SERVICE}" + echo -e "\n Check if $SYSTEMD_SERVICE service is running.." + echo -en " ===============================" + declare -i i=0 + while [[ $i -lt $_length ]] ; do + echo -n "=" + ((i++)) + done + echo "" +fi + +need_restart=false +if $(systemctl is-active $SYSTEMD_SERVICE > /dev/null 2>&1) ; then + eval $(systemctl show -p MainPID ${SYSTEMD_SERVICE}) + if [[ -n "$MainPID" ]] && [[ $MainPID -gt 0 ]]; then + if $(ps ax | grep -q -E "^\s*${MainPID} " 2> /dev/null) ; then + ok "$SYSTEMD_SERVICE service is up and running." + else + error "$SYSTEMD_SERVICE service seems to be down! Trying to restart service now.." + need_restart=true + fi + else + ok "$SYSTEMD_SERVICE service is up and running." + warn "Cannot determine MainPID for Service '$SYSTEMD_SERVICE', but the status is 'active'." + fi + +else + error "$SYSTEMD_SERVICE service seems to be down! Trying to restart service now.." + need_restart=true +fi + +if $need_restart ; then + + $systemctl daemon-reload > /dev/null 2> $log_file + if [[ $? -ne 0 ]]; then + error "$(cat $log_file)" + fi + sleep 2 + $systemctl stop $SYSTEMD_SERVICE > /dev/null 2> $log_file + if [[ $? -ne 0 ]]; then + error "$(cat $log_file)" + fi + sleep 10 + $systemctl start $SYSTEMD_SERVICE > /dev/null 2> $log_file + if [[ $? -ne 0 ]]; then + error "$(cat $log_file)" + fi + + sleep 5 + if $(systemctl is-active $SYSTEMD_SERVICE > /dev/null 2>&1) ; then + eval $(systemctl show -p MainPID ${SYSTEMD_SERVICE}) + if [[ -n "$MainPID" ]] && [[ $MainPID -gt 0 ]]; then + if $(ps ax | grep -q -E "^\s*${MainPID} " 2> /dev/null) ; then + ok "$SYSTEMD_SERVICE service is now up and running. New PID is '$MainPID'" + if ! $terminal ; then + echo " [ Ok ] service is now up and running. New PID is '$MainPID'" + fi + else + error "Restarting $SYSTEMD_SERVICE service failed!" + fi + else + warn "Cannot determine MainPID for Service '$SYSTEMD_SERVICE', but the status is 'active'." + ok "$SYSTEMD_SERVICE service is up and running." + if ! $terminal ; then + echo " [ Ok ] service is now up and running. New PID is '$MainPID'" + echo " [ Warn ] Cannot determine MainPID for Service '$SYSTEMD_SERVICE', but the status is 'active'." + fi + fi + else + error "Restarting $SYSTEMD_SERVICE service failed!" + fi + +fi + +clean_up 0 diff --git a/check_cups-browsed.sh b/check_cups-browsed.sh index 28c5629..1af648e 100755 --- a/check_cups-browsed.sh +++ b/check_cups-browsed.sh @@ -145,7 +145,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_cups.sh b/check_cups.sh index 2e6308d..cd54b2c 100755 --- a/check_cups.sh +++ b/check_cups.sh @@ -145,7 +145,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_dhcp.sh b/check_dhcp.sh index 3b4de0f..b5848f7 100755 --- a/check_dhcp.sh +++ b/check_dhcp.sh @@ -145,7 +145,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_dns.sh b/check_dns.sh index 2f0b568..df31120 100755 --- a/check_dns.sh +++ b/check_dns.sh @@ -172,7 +172,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true else if [[ ! -x $bind_init_script ]]; then diff --git a/check_dovecot.sh b/check_dovecot.sh index f251eb7..6699684 100755 --- a/check_dovecot.sh +++ b/check_dovecot.sh @@ -115,7 +115,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_forwarding.sh b/check_forwarding.sh index 414d98d..bed9c3d 100755 --- a/check_forwarding.sh +++ b/check_forwarding.sh @@ -2,16 +2,179 @@ declare -i val=`cat /proc/sys/net/ipv4/ip_forward` +LOCK_DIR="$(mktemp -d)" + +#--------------------------------------- +#----------------------------- +# Base Function(s) +#----------------------------- +#--------------------------------------- + +fatal(){ + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mFatal\033[m ] $*" + else + echo -e " [ Fatal ] $*" + fi + echo "" + if $terminal ; then + echo -e " \033[1mScript terminated\033[m.." + else + echo -e " Script terminated.." + fi + echo "" + rm -rf $LOCK_DIR + exit 1 +} + +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 (){ + echo "" + if $terminal ; then + echo -e " [ \033[32m\033[1mInfo\033[m ] $*" + else + echo " [ Info ] $*" + fi + echo "" +} + +ok (){ + echo "" + if $terminal ; then + echo -e " [ \033[32m\033[1mOk\033[m ] $*" + else + echo " [ Ok ] $*" + fi + echo "" +} + +trim() { + local var="$*" + var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters + var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters + echo -n "$var" +} + +#----------------------------- +# Check some prerequisites +#----------------------------- +#--------------------------------------- + +# - Running in a terminal? +# - +if [[ -t 1 ]] ; then + terminal=true + LOGGING=true +else + terminal=false + LOGGING=false +fi + + +if $LOGGING ; then + echo -e "\n Check if Forwarding ist activated.." + echo -e " ===================================" +fi + +if [[ $(cat /proc/sys/net/ipv4/ip_forward) -eq 1 ]]; then + if $LOGGING ; then + ok "Forwarding is activated." + fi +else + error "Forwarding seems NOT to be activated. Try to activate forwarding nos.." -if [ $val == 0 ] ; then - echo "activate forwarding .." echo 1 > /proc/sys/net/ipv4/ip_forward + + + if [[ $(cat /proc/sys/net/ipv4/ip_forward) -eq 1 ]]; then + ok "Forwarding is now activated." + else + error "Activating Forwarding failed!" + exit 1 + fi fi -val=`cat /proc/sys/net/ipv4/ip_dynaddr` -if [ $val == 0 ] ; then - echo "activate dynaddr .." - echo 5 > /proc/sys/net/ipv4/ip_dynaddr +VAL=$(cat /proc/sys/net/ipv4/ip_dynaddr) +if [[ "$VAL" -eq 0 ]]; then + error "ip_dynaddr: DEAKTIVIERT ($VAL). Try to set value to '3'.." + + echo 3 > /proc/sys/net/ipv4/ip_dynaddr + + VAL=$(cat /proc/sys/net/ipv4/ip_dynaddr) + + if [[ "$VAL" -eq 3 ]]; then + + ok "ip_dynaddr: AKTIV + Verbose Logging ($VAL)" + + else + + error "Seting '/proc/sys/net/ipv4/ip_dynaddr' to '3' failed!" + exit 1 + fi + +elif [[ "$VAL" -eq 1 ]]; then + + if $LOGGING ; then + + ok "ip_dynaddr: AKTIV ($VAL)." + + fi + +elif [[ "$VAL" -eq 2 ]]; then + + if $LOGGING ; then + + ok "ip_dynaddr: AKTIV + Verbose Logging ($VAL)" + + fi + +elif [[ "$VAL" -eq 3 ]]; then + + if $LOGGING ; then + + ok "ip_dynaddr: AKTIV + Verbose Logging ($VAL)" + + fi + +else + error "ip_dynaddr: UNBEKANNTER WERT ($VAL). Try to set value to '3'.." + + echo 3 > /proc/sys/net/ipv4/ip_dynaddr + + VAL=$(cat /proc/sys/net/ipv4/ip_dynaddr) + + if [[ "$VAL" -eq 3 ]]; then + + ok "ip_dynaddr: AKTIV + Verbose Logging ($VAL)" + + else + + error "Seting '/proc/sys/net/ipv4/ip_dynaddr' to '3' failed!" + exit 1 + fi + fi -exit + +rm -rf $LOCK_DIR +exit 0 diff --git a/check_freshclam.sh b/check_freshclam.sh index 914694b..d8adf4f 100755 --- a/check_freshclam.sh +++ b/check_freshclam.sh @@ -134,7 +134,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_inet_iface_curl.sh b/check_inet_iface_curl.sh new file mode 100755 index 0000000..8ddb8e1 --- /dev/null +++ b/check_inet_iface_curl.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Testet ein Interface mit curl gegen mehrere HTTP/HTTPS-Ziele. +# Online, sobald mindestens EIN Ziel funktioniert. +# Offline erst, wenn ALLE Ziele fehlschlagen. +# Erst der zweite Offline-Fall in Folge erzeugt Meldung + ggf. Aktion. +# +# Usage: +# check_inet_iface_curl.sh [--service NAME | --reboot] [--state-dir DIR] +# [--max-time SEC] [-h|--help] + +IFACE="${1:-}" +shift || true + +# Ziele - echte TCP/HTTPS-Tests +TARGETS=( + "https://oopen.de" + "https://1.1.1.1" + "https://8.8.8.8" + "https://www.debian.org" +) + +CURL_BIN="$(command -v curl)" +DATE_BIN="$(command -v date)" + +STATE_DIR="/run/check_inet" +MAX_TIME=8 +SERVICE="" +DO_REBOOT=0 + +# terminal detection +IS_TTY=0 +if [[ -t 1 || -t 2 ]]; then IS_TTY=1; fi + +# colors (TTY only) +if [[ $IS_TTY -eq 1 ]]; then + RED=$'\e[31m'; GREEN=$'\e[32m'; YELLOW=$'\e[33m'; BOLD=$'\e[1m'; RESET=$'\e[0m' +else + RED=""; GREEN=""; YELLOW=""; BOLD=""; RESET="" +fi + +usage() { + cat <<'USAGE' + +check_inet_iface_curl.sh - prüft Konnektivität per curl über ein bestimmtes Interface. + +Usage: + check_inet_iface_curl.sh [--restart-service NAME | --reboot] [--state-dir DIR] + [--max-time SEC] [-h|--help] + +Optionen: + --restart-service NAME systemd-Service bei 2x OFFLINE in Folge neu starten + --reboot bei 2x OFFLINE in Folge System rebooten + --state-dir DIR State-Verzeichnis (Default: /run/check_inet) + --max-time SEC curl Timeout pro Ziel (Default: 8) + -h, --help Hilfe + +Verhalten: + - Im Terminal: grün "OK" bei Erfolg, rot "FAILED" bei 2x OFFLINE + Details. + - Als Cron (kein TTY): bei Erfolg keine Ausgabe; bei 2x OFFLINE Meldung auf stderr + (damit Cron eine Mail erzeugen kann). + +Exit-Codes: + 0 = online / OK (oder 1. Offline nur gemerkt) + 1 = 2x offline in Folge (Fehler + ggf. Aktion) + 3 = Aktion fehlgeschlagen + +USAGE +} + +clean_up() { + + # Perform program exit housekeeping + blank_line + exit $1 +} + + +log_info() { + if [[ $IS_TTY -eq 1 ]] ; then + echo -e "$*"; + fi +} +log_err() { echo -e "$*" >&2; } + +die() { log_err "${RED}${BOLD}ERROR:${RESET} $*"; exit 64; } +blank_line() { + if [[ $IS_TTY -eq 1 ]] ; then + echo "" + fi +} + +# ----------------------------- +# args +# ----------------------------- +while [[ $# -gt 0 ]]; do + case "$1" in + --restart-service) + [[ $# -ge 2 ]] || die "--restart-service braucht ein Argument" + SERVICE="$2" + shift 2 + ;; + --reboot) + DO_REBOOT=1 + shift + ;; + --state-dir) + [[ $# -ge 2 ]] || die "--state-dir braucht ein Argument" + STATE_DIR="$2" + shift 2 + ;; + --max-time) + [[ $# -ge 2 ]] || die "--max-time braucht ein Argument" + MAX_TIME="$2" + shift 2 + ;; + -h|--help) + usage + clean_up 0 + ;; + *) + die "Unbekannte Option: $1 (verwende -h)" + ;; + esac +done + +if [[ -z "$IFACE" ]]; then + usage >&2 + clean_up 2 +fi + +if [[ -n "$SERVICE" && $DO_REBOOT -eq 1 ]]; then + die "--restart-service und --reboot schließen sich aus" +fi + +STATE_FILE="$STATE_DIR/$IFACE.fail" +mkdir -p "$STATE_DIR" + +# lock gegen parallele cron-runs +LOCK_FD=9 +LOCK_FILE="$STATE_FILE.lock" +exec {LOCK_FD}>"$LOCK_FILE" || true +if command -v flock >/dev/null 2>&1; then + flock -n "$LOCK_FD" || clean_up 0 +fi + +# ------------------------------------------ +# Funktion: Testet ein HTTP(S)-Ziel +# ------------------------------------------ +test_target() { + local target="$1" + # -4 erzwingt IPv4, --interface bindet Source-Interface, + # --max-time begrenzt Timeout, -s silent, -o /dev/null keine Ausgabe + "$CURL_BIN" -4 --interface "$IFACE" --max-time "$MAX_TIME" -s -o /dev/null "$target" +} + +# ------------------------------------------ +# Tests +# ------------------------------------------ +TOTAL="${#TARGETS[@]}" +FAILED=0 +blank_line || true +log_info " Interface: \033[17G$IFACE" +log_info " Targets (${TOTAL}):\033[17G${TARGETS[*]}" +log_info " curl:\033[17G$CURL_BIN max-time: ${MAX_TIME}s" +blank_line || true + +for TG in "${TARGETS[@]}"; do + if test_target "$TG"; then + log_info " ${GREEN}OK${RESET} $TG" + break; + else + FAILED=$((FAILED + 1)) + log_info " ${YELLOW}FAIL${RESET} $TG" + fi +done + +# Wenn mindestens EIN Ziel funktioniert -> online +if [[ $FAILED -lt $TOTAL ]]; then + [[ -f "$STATE_FILE" ]] && rm -f "$STATE_FILE" + if [[ $IS_TTY -eq 1 ]]; then + echo "" + echo -e " ${GREEN}${BOLD}OK${RESET} - Interface ${IFACE}: mindestens ein Ziel erreichbar." + fi + clean_up 0 +fi + +# Alle Ziele fail -> offline +# Erst beim zweiten Mal melden/handeln +TS="$("$DATE_BIN" '+%F %T')" +if [[ -f "$STATE_FILE" ]]; then + if [[ $IS_TTY -eq 1 ]]; then + log_err "" + log_err " ${RED}${BOLD}FAILED${RESET} - ${TS} - Interface ${IFACE}: TCP/HTTP(S) Verbindungen nicht erreichbar! + (curl; Targets: ${TARGETS[*]})" + log_err "" + else + log_err "" + log_err " ${TS} - Interface ${IFACE}: TCP/HTTP(S) Verbindungen nicht erreichbar!" + fi + + # Aktion + if [[ -n "$SERVICE" ]]; then + + log_info " ${YELLOW}Restart Service ${BOLD}$SERVICE${RESET}" + log_info "" + + if systemctl restart "$SERVICE" >/dev/null 2>&1; then + if [[ $IS_TTY -eq 1 ]] ; then + log_err " ${GREEN}Service neugestartet:${RESET} $SERVICE" + else + log_err " ${TS} - Service neugestartet: $SERVICE" + log_err "" + fi + clean_up 1 + else + if [[ $IS_TTY -eq 1 ]] ; then + log_err " ${RED}Service-Restart fehlgeschlagen:${RESET} $SERVICE" + else + log_err "" + log_err " ${TS} - Service-Restart fehlgeschlagen: $SERVICE" + log_err "" + fi + clean_up 3 + fi + elif [[ $DO_REBOOT -eq 1 ]]; then + if [[ $IS_TTY -eq 1 ]]; then + log_err " ${YELLOW}${BOLD}Resboot machine NOW!${RESET}" + log_err "" + else + log_err " ${TS} - Resboot machine NOW!" + log_err "" + fi + + /sbin/reboot >/dev/null 2>&1 || { log_err "${RED}Reboot fehlgeschlagen.${RESET}"; clean_up 3; } + clean_up 1 + fi + + #clean_up 1 +else + # Erster Offline-Fall -> noch keine Meldung + touch "$STATE_FILE" + if [[ $IS_TTY -eq 1 ]]; then + log_info "" + log_info " ${YELLOW}${BOLD}WARN${RESET} - Interface ${IFACE} offline (das erste mal - noch keine Aktion/Meldung)." + else + log_err " ${TS} - Interface ${IFACE} offline (first time - no action started)" + fi + clean_up 0 +fi + diff --git a/check_inet_iface_ping.sh b/check_inet_iface_ping.sh new file mode 100755 index 0000000..2e5dd16 --- /dev/null +++ b/check_inet_iface_ping.sh @@ -0,0 +1,251 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Testet ein Interface mit curl gegen mehrere HTTP/HTTPS-Ziele. +# Online, sobald mindestens EIN Ziel funktioniert. +# Offline erst, wenn ALLE Ziele fehlschlagen. +# Erst der zweite Offline-Fall in Folge erzeugt Meldung + ggf. Aktion. +# +# Usage: +# check_inet_iface_curl.sh [--service NAME | --reboot] [--state-dir DIR] +# [--max-time SEC] [-h|--help] + +IFACE="${1:-}" +shift || true + +# Ziele - echte TCP/HTTPS-Tests +TARGETS=( + "oopen.de" + "1.1.1.1" + "8.8.8.8" + "www.debian.org" +) + +PING_BIN="$(command -v ping)" +DATE_BIN="$(command -v date)" +TIMEOUT_BIN="$(command -v timeout)" + +STATE_DIR="/run/check_inet" +MAX_TIME=8 +SERVICE="" +DO_REBOOT=0 + +# terminal detection +IS_TTY=0 +if [[ -t 1 || -t 2 ]]; then IS_TTY=1; fi + +# colors (TTY only) +if [[ $IS_TTY -eq 1 ]]; then + RED=$'\e[31m'; GREEN=$'\e[32m'; YELLOW=$'\e[33m'; BOLD=$'\e[1m'; RESET=$'\e[0m' +else + RED=""; GREEN=""; YELLOW=""; BOLD=""; RESET="" +fi + +usage() { + cat <<'USAGE' + +check_inet_iface_curl.sh - prüft Konnektivität per curl über ein bestimmtes Interface. + +Usage: + check_inet_iface_curl.sh [--restart-service NAME | --reboot] [--state-dir DIR] + [--max-time SEC] [-h|--help] + +Optionen: + --restart-service NAME systemd-Service bei 2x OFFLINE in Folge neu starten + --reboot bei 2x OFFLINE in Folge System rebooten + --state-dir DIR State-Verzeichnis (Default: /run/check_inet) + --max-time SEC curl Timeout pro Ziel (Default: 8) + -h, --help Hilfe + +Verhalten: + - Im Terminal: grün "OK" bei Erfolg, rot "FAILED" bei 2x OFFLINE + Details. + - Als Cron (kein TTY): bei Erfolg keine Ausgabe; bei 2x OFFLINE Meldung auf stderr + (damit Cron eine Mail erzeugen kann). + +Exit-Codes: + 0 = online / OK (oder 1. Offline nur gemerkt) + 1 = 2x offline in Folge (Fehler + ggf. Aktion) + 3 = Aktion fehlgeschlagen + +USAGE +} + +clean_up() { + + # Perform program exit housekeeping + blank_line + exit $1 +} + + +log_info() { + if [[ $IS_TTY -eq 1 ]] ; then + echo -e "$*"; + fi +} +log_err() { echo -e "$*" >&2; } + +die() { log_err "${RED}${BOLD}ERROR:${RESET} $*"; exit 64; } +blank_line() { + if [[ $IS_TTY -eq 1 ]] ; then + echo "" + fi +} + +# ----------------------------- +# args +# ----------------------------- +while [[ $# -gt 0 ]]; do + case "$1" in + --restart-service) + [[ $# -ge 2 ]] || die "--restart-service braucht ein Argument" + SERVICE="$2" + shift 2 + ;; + --reboot) + DO_REBOOT=1 + shift + ;; + --state-dir) + [[ $# -ge 2 ]] || die "--state-dir braucht ein Argument" + STATE_DIR="$2" + shift 2 + ;; + --max-time) + [[ $# -ge 2 ]] || die "--max-time braucht ein Argument" + MAX_TIME="$2" + shift 2 + ;; + -h|--help) + usage + clean_up 0 + ;; + *) + die "Unbekannte Option: $1 (verwende -h)" + ;; + esac +done + +if [[ -z "$IFACE" ]]; then + usage >&2 + clean_up 2 +fi + +if [[ -n "$SERVICE" && $DO_REBOOT -eq 1 ]]; then + die "--restart-service und --reboot schließen sich aus" +fi + +STATE_FILE="$STATE_DIR/$IFACE.fail" +mkdir -p "$STATE_DIR" + +# lock gegen parallele cron-runs +LOCK_FD=9 +LOCK_FILE="$STATE_FILE.lock" +exec {LOCK_FD}>"$LOCK_FILE" || true +if command -v flock >/dev/null 2>&1; then + flock -n "$LOCK_FD" || clean_up 0 +fi + +# ------------------------------------------ +# Funktion: Testet ein HTTP(S)-Ziel +# ------------------------------------------ +test_target() { + local target="$1" + $TIMEOUT_BIN $MAX_TIME $PING_BIN -I "$IFACE" -c 2 -W 2 "$target" >/dev/null 2>&1 +} + +# ------------------------------------------ +# Tests +# ------------------------------------------ +TOTAL="${#TARGETS[@]}" +FAILED=0 +blank_line || true +log_info " Interface: \033[17G$IFACE" +log_info " Targets (${TOTAL}):\033[17G${TARGETS[*]}" +log_info " ping:\033[17G$PING_BIN timeout: ${MAX_TIME}s" +blank_line || true + +for TG in "${TARGETS[@]}"; do + if test_target "$TG"; then + log_info " ${GREEN}OK${RESET} $TG" + break; + else + FAILED=$((FAILED + 1)) + log_info " ${YELLOW}FAIL${RESET} $TG" + fi +done + +# Wenn mindestens EIN Ziel funktioniert -> online +if [[ $FAILED -lt $TOTAL ]]; then + [[ -f "$STATE_FILE" ]] && rm -f "$STATE_FILE" + if [[ $IS_TTY -eq 1 ]]; then + echo "" + echo -e " ${GREEN}${BOLD}OK${RESET} - Interface ${IFACE}: mindestens ein Ziel erreichbar." + fi + clean_up 0 +fi + +# Alle Ziele fail -> offline +# Erst beim zweiten Mal melden/handeln +TS="$("$DATE_BIN" '+%F %T')" +if [[ -f "$STATE_FILE" ]]; then + if [[ $IS_TTY -eq 1 ]]; then + log_err "" + log_err " ${RED}${BOLD}FAILED${RESET} - ${TS} - Interface ${IFACE}: TCP/HTTP(S) Verbindungen nicht erreichbar! + (curl; Targets: ${TARGETS[*]})" + log_err "" + else + log_err "" + log_err " ${TS} - Interface ${IFACE}: PING Verbindungen nicht erreichbar!" + fi + + # Aktion + if [[ -n "$SERVICE" ]]; then + + log_info " ${YELLOW}Restart Service ${BOLD}$SERVICE${RESET}" + log_info "" + + if systemctl restart "$SERVICE" >/dev/null 2>&1; then + if [[ $IS_TTY -eq 1 ]] ; then + log_err " ${GREEN}Service neugestartet:${RESET} $SERVICE" + else + log_err " ${TS} - Service neugestartet: $SERVICE" + log_err "" + fi + clean_up 1 + else + if [[ $IS_TTY -eq 1 ]] ; then + log_err " ${RED}Service-Restart fehlgeschlagen:${RESET} $SERVICE" + else + log_err "" + log_err " ${TS} - Service-Restart fehlgeschlagen: $SERVICE" + log_err "" + fi + clean_up 3 + fi + elif [[ $DO_REBOOT -eq 1 ]]; then + if [[ $IS_TTY -eq 1 ]]; then + log_err " ${YELLOW}${BOLD}Resboot machine NOW!${RESET}" + log_err "" + else + log_err " ${TS} - Resboot machine NOW!" + log_err "" + fi + + /sbin/reboot >/dev/null 2>&1 || { log_err "${RED}Reboot fehlgeschlagen.${RESET}"; clean_up 3; } + clean_up 1 + fi + + #clean_up 1 +else + # Erster Offline-Fall -> noch keine Meldung + touch "$STATE_FILE" + if [[ $IS_TTY -eq 1 ]]; then + log_info "" + log_info " ${YELLOW}${BOLD}WARN${RESET} - Interface ${IFACE} offline (das erste mal - noch keine Aktion/Meldung)." + else + log_err " ${TS} - Interface ${IFACE} offline (first time - no action started)" + fi + clean_up 0 +fi + diff --git a/check_local_webservice.sh b/check_local_webservice.sh index e9fc109..af86af9 100755 --- a/check_local_webservice.sh +++ b/check_local_webservice.sh @@ -317,7 +317,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_networking.sh b/check_networking.sh index 9ff1a3f..8411806 100755 --- a/check_networking.sh +++ b/check_networking.sh @@ -151,7 +151,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true else fatal "Support of systemd is requirred for this script" diff --git a/check_nginx_service.sh b/check_nginx_service.sh index 26e26ec..b1d4c35 100755 --- a/check_nginx_service.sh +++ b/check_nginx_service.sh @@ -151,7 +151,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_ntpd.sh b/check_ntpd.sh index 744adf5..7f4fc3a 100755 --- a/check_ntpd.sh +++ b/check_ntpd.sh @@ -145,7 +145,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_ntpsec_service.sh b/check_ntpsec_service.sh index 923b2fa..8e3b82a 100755 --- a/check_ntpsec_service.sh +++ b/check_ntpsec_service.sh @@ -151,7 +151,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_postfix.sh b/check_postfix.sh index 0d05292..84c6b46 100755 --- a/check_postfix.sh +++ b/check_postfix.sh @@ -145,7 +145,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true else if [[ ! -x $postfix_init_script ]]; then diff --git a/check_postfwd.sh b/check_postfwd.sh index f0da371..0eeb045 100755 --- a/check_postfwd.sh +++ b/check_postfwd.sh @@ -134,7 +134,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_postgrey.sh b/check_postgrey.sh index b11e3db..6968968 100755 --- a/check_postgrey.sh +++ b/check_postgrey.sh @@ -134,7 +134,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_prosody_auth.sh b/check_prosody_auth.sh new file mode 100755 index 0000000..863abb7 --- /dev/null +++ b/check_prosody_auth.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# -------------------- +# This script checks whether the 'prosody' service has logged any Dovecot authentication errors within +# the last check interval (MONITORING_INTERVAL) +# +# It is a good idea to run this script as a cron job every check interval minutes (MONITORING_INTERVAL). +# -------------------- + +LOGFILE="/var/log/prosody_auth_check.log" +TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') +DOVECOT_HOST="a.mx.oopen.de" +DOVECOT_PORT="44444" +MONITORING_INTERVAL=6 + +# Test 1: Ist Dovecot überhaupt erreichbar? +if ! timeout 8 bash -c "echo >/dev/tcp/$DOVECOT_HOST/$DOVECOT_PORT" 2>/dev/null; then + echo "$TIMESTAMP WARN: Dovecot nicht erreichbar - Prosody-Restart wäre sinnlos, überspringe" >> $LOGFILE + exit 1 +fi + +# Test 2: Genau der bekannte Fehler in den letzten 6 Minuten? +ERROR_COUNT=$(journalctl -u prosody --since "${MONITORING_INTERVAL} minutes ago" --no-pager 2>/dev/null | \ + grep -c "sasl_dovecot: Could not read from socket" || true) + +if [ "$ERROR_COUNT" -gt 0 ]; then + echo "$TIMESTAMP ERROR: sasl_dovecot socket-Fehler erkannt ($ERROR_COUNT×) – starte Prosody neu" >> $LOGFILE + systemctl restart prosody + sleep 5 + if systemctl is-active --quiet prosody; then + echo "$TIMESTAMP OK: Prosody erfolgreich neugestartet" >> $LOGFILE + else + echo "$TIMESTAMP CRITICAL: Prosody-Neustart fehlgeschlagen!" >> $LOGFILE + fi + exit 0 +fi + +echo "$TIMESTAMP OK: Keine Auth-Fehler" >> $LOGFILE diff --git a/check_remote_websites.sh b/check_remote_websites.sh index 4437198..2fa4dce 100755 --- a/check_remote_websites.sh +++ b/check_remote_websites.sh @@ -186,7 +186,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_samba4_service.sh b/check_samba4_service.sh index 16c6439..01ac9c6 100755 --- a/check_samba4_service.sh +++ b/check_samba4_service.sh @@ -147,7 +147,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_service.sh b/check_service.sh index ed483d1..b6da24c 100755 --- a/check_service.sh +++ b/check_service.sh @@ -107,7 +107,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_ssh.sh b/check_ssh.sh index f591cd0..096cb56 100755 --- a/check_ssh.sh +++ b/check_ssh.sh @@ -110,7 +110,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_sympa_service.sh b/check_sympa_service.sh index d52a040..325a315 100755 --- a/check_sympa_service.sh +++ b/check_sympa_service.sh @@ -195,7 +195,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/check_systemd_resolved.sh b/check_systemd_resolved.sh new file mode 100755 index 0000000..71d44bb --- /dev/null +++ b/check_systemd_resolved.sh @@ -0,0 +1,334 @@ +#!/usr/bin/env bash + +LOCK_DIR="/tmp/$(basename $0).$$.LOCK" +log_file="${LOCK_DIR}/${script_name%%.*}.log" + +CONFLICTING_SCRIPTS="" + +service_name=systemd-resolved + + +#--------------------------------------- +#----------------------------- +# Base Function(s) +#----------------------------- +#--------------------------------------- + +usage() { + + + [[ -n "$1" ]] && error "$1" + + + [[ $terminal ]] && echo -e " +\033[1mUsage:\033[m + + $(basename $0) + +\033[1mDescription\033[m + + Script checks if given service is running and tries to restart service + if it is not running. + +\033[1mOptions\033[m + + No Options available + +\033[1mExample:\033[m + + Check if apache2 service is runnin. Restart service if needed. + + $(basename $0) apache2 + +" + + clean_up 1 +} + + +clean_up() { + + # Perform program exit housekeeping + rm -rf "$LOCK_DIR" + blank_line + exit $1 +} + + +fatal(){ + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mFatal\033[m ] $*" + else + echo -e " [ Fatal ] $*" + fi + echo "" + if $terminal ; then + echo -e " \033[1mScript terminated\033[m.." + else + echo -e " Script terminated.." + fi + clean_up 1 +} + +error (){ + echo "" + if $terminal ; then + echo -e " [ \033[31m\033[1mError\033[m ] $*" + else + echo " [ Error ] $*" + fi + echo "" +} + +warn (){ + if $LOGGING || $terminal ; then + echo "" + if $terminal ; then + echo -e " [ \033[33m\033[1mWarn\033[m ] $*" + else + echo " [ Warn ] $*" + fi + echo "" + fi +} + +info (){ + if $LOGGING || $terminal ; then + echo "" + if $terminal ; then + echo -e " [ \033[32m\033[1mInfo\033[m ] $*" + else + echo " [ Info ] $*" + fi + echo "" + fi +} + +ok (){ + if $LOGGING || $terminal ; then + echo "" + if $terminal ; then + echo -e " [ \033[32m\033[1mOk\033[m ] $*" + else + echo " [ Ok ] $*" + fi + echo "" + fi +} + +warn_only_terminal () { + if $terminal ; then + echo "" + echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*" + echo "" + fi +} + +blank_line() { + if $terminal ; then + echo "" + fi +} + +trim() { + local var="$*" + var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters + var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters + echo -n "$var" +} + +# - Running in a terminal? +# - +if [[ -t 1 ]] ; then + terminal=true + LOGGING=true +else + terminal=false + LOGGING=false +fi + + +# ---------- +# - Jobhandling +# ---------- + +# - Run 'clean_up' for signals SIGHUP SIGINT SIGTERM +# - +trap clean_up SIGHUP SIGINT SIGTERM + +# - Create lock directory '$LOCK_DIR" +# +mkdir "$LOCK_DIR" + + +# - Stop here, if these give scripts are running +# - +if [[ ${#CONFLICTING_SCRIPTS} -gt 0 ]] ; then + + # - Try using a random start delay to prevent (or at least have a small chance) that + # - conflicting scripts will both/all abort if they start at the same time. + # - + # - !! Notice !! + # - This only makes sense if a fixed LOCK directory is used, otherwise the process list + # - (and NOT the LOCK-directory) is used to look for scripts running in parallel. + # - + # - Skip delay if running in an terminal (from copnsole) + # - + if ! $terminal ; then + if [[ "$LOCK_DIR" = "/tmp/${script_name%%.*}.LOCK" ]]; then + _shift="$(( $RANDOM % 10 + 1 ))" + sleep $(( $RANDOM % 25 + $_shift )) + fi + fi + + _stop_running=false + for _val in $CONFLICTING_SCRIPTS ; do + + IFS=':' read -a _val_arr <<< "${_val}" + + _script_name="$(basename ${_val_arr[0]})" + + if [[ -n "${_val_arr[1]}" ]] ; then + + if [[ "${_val_arr[1]}" = "CHECK_PROCESS_LIST" ]] ; then + + check_string_ps="${_val_arr[0]}" + if ps -e f | grep -E "\s+${check_string_ps}" | grep -v grep | grep -v -E "\s+vim\s+" > /dev/null ; then + _stop_running=true + fi + + elif [[ -d "${_val_arr[1]}" ]] ; then + _stop_running=true + fi + + elif [[ -d "/tmp/${_script_name%%.*}.LOCK" ]]; then + _stop_running=true + fi + + if $_stop_running ; then + + warn_only_terminal "\033[1m${_script_name}\033[m is currently running, but it conflicts with this script. + + Exiting now.." + + clean_up 1 + + fi # if $_stop_running ; then + + done # for _val in $CONFLICTING_SCRIPTS ; do + +fi # if [[ ${#CONFLICTING_SCRIPTS} -gt 0 ]] ; then + + + +#--------------------------------------- +#----------------------------- +# Check some prerequisites +#----------------------------- +#--------------------------------------- + +systemctl="$(which systemctl)" +if [[ -z "${systemctl}" ]] ; then + fatal "Systemd service seems not be installed!" +fi + +if systemctl -t service list-unit-files \ + | grep -e "^${service_name,,}d" \ + | grep -q -E "(enabled|disabled)" 2> /devnull ; then + + SYSTEMD_SERVICE="$(systemctl -t service list-unit-files | grep -e "^${service_name,,}d" | awk '{print$1}' | head -1)" +elif systemctl -t service list-unit-files \ + | grep -e "^${service_name,,}" \ + | grep -q -E "(enabled|disabled)" 2> /devnull ; then + + SYSTEMD_SERVICE="$(systemctl -t service list-unit-files | grep -e "^${service_name,,}" | awk '{print$1}' | head -1)" +fi + +if [[ -z "$SYSTEMD_SERVICE" ]]; then + fatal "Systemd Service '${service_name}' not found!" +fi + + +#--------------------------------------- +#----------------------------- +# Check if service is running +#----------------------------- +#--------------------------------------- + +if $LOGGING ; then + declare -i _length="${#service_name}" + echo -e "\n Check if $service_name service is running.." + echo -en " ===============================" + declare -i i=0 + while [[ $i -lt $_length ]] ; do + echo -n "=" + ((i++)) + done + echo "" +fi + +need_restart=false +if $(systemctl is-active $SYSTEMD_SERVICE > /dev/null 2>&1) ; then + eval $(systemctl show -p MainPID ${SYSTEMD_SERVICE}) + if [[ -n "$MainPID" ]] && [[ $MainPID -gt 0 ]]; then + if $(ps ax | grep -q -E "^\s*${MainPID} " 2> /dev/null) ; then + ok "$service_name service is up and running." + else + error "$service_name service seems to be down! Trying to restart service now.." + need_restart=true + fi + else + ok "$service_name service is up and running." + warn "Cannot determine MainPID for Service '$service_name', but the status is 'active'." + fi + +else + error "$service_name service seems to be down! Trying to restart service now.." + need_restart=true +fi + +if $need_restart ; then + + $systemctl daemon-reload > /dev/null 2> $log_file + if [[ $? -ne 0 ]]; then + error "$(cat $log_file)" + fi + sleep 2 + $systemctl stop $SYSTEMD_SERVICE > /dev/null 2> $log_file + if [[ $? -ne 0 ]]; then + error "$(cat $log_file)" + fi + sleep 10 + $systemctl start $SYSTEMD_SERVICE > /dev/null 2> $log_file + if [[ $? -ne 0 ]]; then + error "$(cat $log_file)" + fi + + sleep 5 + if $(systemctl is-active $SYSTEMD_SERVICE > /dev/null 2>&1) ; then + eval $(systemctl show -p MainPID ${SYSTEMD_SERVICE}) + if [[ -n "$MainPID" ]] && [[ $MainPID -gt 0 ]]; then + if $(ps ax | grep -q -E "^\s*${MainPID} " 2> /dev/null) ; then + ok "$service_name service is now up and running. New PID is '$MainPID'" + if ! $terminal ; then + echo " [ Ok ] service is now up and running. New PID is '$MainPID'" + fi + else + error "Restarting $service_name service failed!" + fi + else + warn "Cannot determine MainPID for Service '$service_name', but the status is 'active'." + ok "$service_name service is up and running." + if ! $terminal ; then + echo " [ Ok ] service is now up and running. New PID is '$MainPID'" + echo " [ Warn ] Cannot determine MainPID for Service '$service_name', but the status is 'active'." + fi + fi + else + error "Restarting $service_name service failed!" + fi + +fi + +clean_up 0 diff --git a/check_vpn.sh b/check_vpn.sh index f0d644d..ec6fa22 100755 --- a/check_vpn.sh +++ b/check_vpn.sh @@ -140,7 +140,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true else if [[ ! -x $init_script ]]; then diff --git a/check_webservice_load.sh b/check_webservice_load.sh index a6c7bdf..ce11a12 100755 --- a/check_webservice_load.sh +++ b/check_webservice_load.sh @@ -345,7 +345,7 @@ if ! $vserver_guest ; then systemd=$(which systemd) systemctl=$(which systemctl) - if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then + if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi fi diff --git a/check_wwsympa_service.sh b/check_wwsympa_service.sh index 7c1bef6..252d87f 100755 --- a/check_wwsympa_service.sh +++ b/check_wwsympa_service.sh @@ -189,7 +189,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/conf/check_cert_for_keycloak.conf.sample b/conf/check_cert_for_keycloak.conf.sample new file mode 100644 index 0000000..9a0c1f3 --- /dev/null +++ b/conf/check_cert_for_keycloak.conf.sample @@ -0,0 +1,123 @@ +# ---------------------------------------------- +# Settings for script check_cert_for_keycloak.sh +# ---------------------------------------------- + +# - service_domain +# - +#service_domain="" + + +# - service_name +# - +# - Name of service. +# - +# - Note: this var will also be used to determin systemd service file +# - or sysVinit script. +# - +# - Example: +# - service_name="Mumble" +# - service_name="Prosody" +# - +# - Defaults to: +# - service_name="Prosody" +# - +#service_name="" + + +# - check_string_ps +# - +# - String wich (clearly) identifies the service at the process list (ps) +# - +# - Example: +# - check_string_ps="[[:digit:]]\ /usr/sbin/murmurd" +# - check_string_ps="" +# - +# - Defaults to: +# - check_string_ps="[[:digit:]]\ lua[[:digit:]].[[:digit:]] /usr/bin/prosody" +# - +#check_string_ps="" + + +# - service_user +# - +# - User under which the service is running. +# - +# - Example: +# - service_user="mumble-server" +# - service_user="prosody" +# - +# - Defaults to: +# - service_user="prosody" +# - +#service_user="" + + +# - service_group +# - +# - Group under which the service is running. +# - +# - Example: +# - service_group="mumble-server" +# - service_group="prosody" +# - +# - Defaults to: +# - service_group="prosody" +# - +#service_group="" + + +# - cert_installed +# - +# - Locataion of certificate read by service +# - +# - Example: +# - cert_installed="/var/lib/mumble-server/fullchain.pem" +# - cert_installed="/var/lib/dehydrated/certs/jabber.so36.net/fullchain.pem" +# - +# - Defaults to: +# - /etc/prosody/certs/${service_domain}.crt +# - +#cert_installed="" + + +# - key_installed +# - +# - Location of the key read by service +# - +# - Example: +# - key_installed="/var/lib/mumble-server/privkey.pem" +# - key_installed="/etc/prosody/certs/privkey_jabber.so36.pem" +# - +# - Defaults to: +# - /etc/prosody/certs/${service_domain}.key +# - +#key_installed="" + + +# - cert_newest +# - +# - Location of the newest certificate. +# - +# - Example: +# - cert_newest="/var/lib/dehydrated/certs/il-mumble.oopen.de/fullchain.pem" +# - cert_newest="/var/lib/dehydrated/certs/jabber.so36.net/fullchain.pem" +# - +# - Defaults to: +# - /var/lib/dehydrated/certs/${service_domain}/fullchain.pem +# - +#cert_newest="" + + +# - key_newest +# - +# - Location of the newest Key +# - +# - Example: +# - key_newest="/var/lib/dehydrated/certs/il-mumble.oopen.de/privkey.pem" +# - key_newest="/var/lib/dehydrated/certs/jabber.so36.net/privkey.pem" +# - +# - Defaults to: +# - /var/lib/dehydrated/certs/${service_domain}/privkey.pem +# - +#key_newest="" + diff --git a/conf/traffic-peak-monitor-IFACE.conf.sample b/conf/traffic-peak-monitor-IFACE.conf.sample new file mode 100644 index 0000000..cc96f6c --- /dev/null +++ b/conf/traffic-peak-monitor-IFACE.conf.sample @@ -0,0 +1,107 @@ +# ============================================================================ +# traffic-peak-monitor-IFACE.conf.sample +# ============================================================================ +# +# Beispiel-/Vorlagen-Konfiguration fuer traffic-peak-monitor.sh +# +# VERWENDUNG: +# 1. Diese Datei kopieren und "IFACE" im Dateinamen durch den echten +# Namen des zu ueberwachenden Netzwerk-Interfaces ersetzen. +# Der Dateiname MUSS folgendem Schema entsprechen: +# +# traffic-peak-monitor-.conf +# +# Beispiele: +# cp traffic-peak-monitor-IFACE.conf.sample traffic-peak-monitor-lan4.conf +# cp traffic-peak-monitor-IFACE.conf.sample traffic-peak-monitor-lan4.11.conf +# +# 2. Werte unten an die tatsaechlichen Gegebenheiten anpassen. +# +# 3. Die Endung ".sample" ist wichtig: Dateien mit dieser Endung werden +# vom Launcher-Modus des Scripts NICHT eingelesen (nur echte +# *.conf Dateien werden gesucht) - diese Datei hier kann also +# gefahrlos als Vorlage im conf/-Verzeichnis liegen bleiben, ohne +# selbst einen Monitoring-Prozess auszuloesen. +# +# HINWEIS: +# Diese Datei wird von "traffic-peak-monitor.sh" per "source" eingelesen, +# d.h. es ist technisch gesehen ein kleines Bash-Script. Nur einfache +# Variablenzuweisungen verwenden (VARIABLE=wert), keine Leerzeichen um +# das "=", keine Shell-Kommandos einfuegen. +# +# ============================================================================ + + +# ---------------------------------------------------------------------- +# INTERVAL - Messintervall in Sekunden +# ---------------------------------------------------------------------- +# Legt fest, wie oft der Byte-Zaehler des Interfaces ausgelesen wird, um +# daraus die aktuelle Uebertragungsrate zu berechnen. +# +# Je KLEINER der Wert, desto GENAUER werden kurze Lastspitzen erfasst - +# ein Peak, der nur 1-2 Sekunden dauert, wird bei INTERVAL=10 evtl. gar +# nicht oder nur stark abgeschwaecht sichtbar, weil er "weggemittelt" wird. +# +# Je KLEINER der Wert, desto MEHR (minimale) Last erzeugt die Messung +# selbst, da haeufiger Dateien gelesen und Berechnungen durchgefuehrt +# werden. Fuer ein einzelnes Interface ist das i.d.R. vernachlaessigbar. +# +# Empfehlung: +# 2 = guter Kompromiss aus Genauigkeit und Overhead (Standard) +# 1 = sehr genau, minimal mehr Last +# 5-10 = grober, reicht z.B. bei eher traegen/gleichmaessigen Leitungen +# +# Default im Script, falls hier nicht gesetzt: 2 +INTERVAL=2 + + +# ---------------------------------------------------------------------- +# LINE_SPEED_IN_MBIT - Download-Kapazitaet der Leitung in Mbit/s +# ---------------------------------------------------------------------- +# Die maximale EINGEHENDE (rx) Bandbreite der Leitung, an der dieses +# Interface haengt - also das, was z.B. im Vertrag mit dem Provider als +# "Download-Geschwindigkeit" angegeben ist. +# +# Wird verwendet, um die gemessenen rx-Spitzenwerte als Prozentwert der +# verfuegbaren Kapazitaet auszugeben (z.B. "45.2%" bedeutet: die Spitze +# hat 45,2 % der theoretisch moeglichen Download-Rate ausgenutzt). +# +# WICHTIG: Angabe in Mbit/s (Megabit), NICHT MByte/s (Megabyte). +# Netzwerk-Bandbreiten werden ueblicherweise in Bit/s angegeben - genau +# wie es auch im Vertrag beim Provider steht (z.B. "100 Mbit/s Download"). +# +# Beispiel-Werte gaengiger Anschluesse: +# DSL 50/10 -> LINE_SPEED_IN_MBIT=50 +# DSL 100/40 -> LINE_SPEED_IN_MBIT=100 +# Kabel 500/50 -> LINE_SPEED_IN_MBIT=500 +# Glasfaser 1000/500 -> LINE_SPEED_IN_MBIT=1000 +# +# Default im Script, falls hier nicht gesetzt: 100 +LINE_SPEED_IN_MBIT=100 + + +# ---------------------------------------------------------------------- +# LINE_SPEED_OUT_MBIT - Upload-Kapazitaet der Leitung in Mbit/s +# ---------------------------------------------------------------------- +# Die maximale AUSGEHENDE (tx) Bandbreite der Leitung - also die +# "Upload-Geschwindigkeit" laut Vertrag. +# +# Viele Anschluesse sind ASYMMETRISCH, d.h. Download- und Upload-Rate +# unterscheiden sich deutlich (z.B. DSL 100/40 = 100 Mbit/s Download, +# aber nur 40 Mbit/s Upload). Deshalb wird dieser Wert getrennt von +# LINE_SPEED_IN_MBIT angegeben - eine gemeinsame Prozentrechnung ueber +# einen einzigen Wert wuerde bei asymmetrischen Anschluessen falsche +# bzw. irrefuehrende Prozentzahlen liefern. +# +# Beispiel-Werte gaengiger Anschluesse (Fortsetzung von oben): +# DSL 50/10 -> LINE_SPEED_OUT_MBIT=10 +# DSL 100/40 -> LINE_SPEED_OUT_MBIT=40 +# Kabel 500/50 -> LINE_SPEED_OUT_MBIT=50 +# Glasfaser 1000/500 -> LINE_SPEED_OUT_MBIT=500 +# +# Bei SYMMETRISCHEN Anschluessen (z.B. manche Glasfaser-Vertraege mit +# z.B. 1000/1000) einfach den gleichen Wert wie bei LINE_SPEED_IN_MBIT +# eintragen. +# +# Default im Script, falls hier nicht gesetzt: 100 +LINE_SPEED_OUT_MBIT=100 diff --git a/systemd-service-files/traffic-peak-monitor.service b/systemd-service-files/traffic-peak-monitor.service new file mode 100644 index 0000000..647273a --- /dev/null +++ b/systemd-service-files/traffic-peak-monitor.service @@ -0,0 +1,40 @@ +# traffic-peak-monitor.service +# ------------------------------ +# Startet den traffic-peak-monitor.sh im Launcher-Modus (ohne Parameter). +# Der Launcher durchsucht selbststaendig das conf/-Verzeichnis und startet +# fuer jede gefundene Konfigurationsdatei einen eigenen Worker-Prozess. +# +# Es wird also NUR EINE einzige Service-Instanz benoetigt, unabhaengig +# davon wie viele Interfaces (lan4, lan4.11, ...) ueberwacht werden - +# neue Interfaces werden einfach per neuer .conf-Datei in conf/ +# hinzugefuegt, ohne die Service-Datei anzufassen. +# +# Installation: +# cp traffic-peak-monitor.service /etc/systemd/system/ +# systemctl daemon-reload +# systemctl enable --now traffic-peak-monitor.service +# +# Hinweis: Um eine neue .conf-Datei zu aktivieren, muss der Service +# neu gestartet werden (systemctl restart traffic-peak-monitor.service), +# damit der Launcher erneut nach Konfigurationen sucht. + +[Unit] +Description=Traffic Peak Monitor (Launcher fuer alle konfigurierten Interfaces) +After=network.target + +[Service] +# Kein "sudo" noetig - der Service laeuft laut [Service]-Block unten +# bereits direkt als root (User=root) +User=root + +# Launcher-Modus: ohne Parameter aufrufen, das Script findet seine +# Konfigurationen selbststaendig im conf/-Unterverzeichnis +ExecStart=/root/bin/monitoring/traffic-peak-monitor.sh + +# Falls der Launcher (oder einer seiner Worker-Kindprozesse, wodurch +# "wait" im Script zurueckkehrt) unerwartet endet, automatisch neu starten +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target diff --git a/testscript-running-30-seconds-with-dynamic-LOCK_DIR.sh b/testscript-running-30-seconds-with-dynamic-LOCK_DIR.sh index 94fd4c6..89f9cbf 100755 --- a/testscript-running-30-seconds-with-dynamic-LOCK_DIR.sh +++ b/testscript-running-30-seconds-with-dynamic-LOCK_DIR.sh @@ -101,7 +101,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/testscript-running-30-seconds-with-static-LOCK_DIR.sh b/testscript-running-30-seconds-with-static-LOCK_DIR.sh index 633f6aa..d6da244 100755 --- a/testscript-running-30-seconds-with-static-LOCK_DIR.sh +++ b/testscript-running-30-seconds-with-static-LOCK_DIR.sh @@ -137,7 +137,7 @@ systemd=$(which systemd) systemctl=$(which systemctl) systemd_supported=false -if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then +if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then systemd_supported=true fi diff --git a/traffic-peak-monitor.sh b/traffic-peak-monitor.sh new file mode 100755 index 0000000..d19b413 --- /dev/null +++ b/traffic-peak-monitor.sh @@ -0,0 +1,243 @@ +#!/bin/bash +# +# traffic-peak-monitor.sh +# ------------------------ +# Ermittelt fuer ein Netzwerk-Interface die stuendlichen Spitzenwerte +# (Peaks) der ein- und ausgehenden Datenrate und schreibt sie stuendlich +# in eine Log-Datei. +# +# AUFRUF-MODI: +# +# 1) OHNE Parameter -> "Launcher-Modus" +# ./traffic-peak-monitor.sh +# Durchsucht das Verzeichnis "conf/" nach allen passenden +# Konfigurationsdateien (traffic-peak-monitor-*.conf), z.B.: +# conf/traffic-peak-monitor-lan4.conf +# conf/traffic-peak-monitor-lan4.11.conf +# und startet fuer JEDE gefundene Konfiguration einen eigenen +# Hintergrundprozess (das Script ruft sich dabei selbst im +# Worker-Modus auf, einmal pro Interface). +# +# 2) MIT Interface-Namen als Parameter -> "Worker-Modus" +# ./traffic-peak-monitor.sh lan4 +# Ueberwacht genau dieses eine Interface dauerhaft. Wird normal- +# erweise nicht manuell aufgerufen, sondern automatisch vom +# Launcher-Modus gestartet. +# +# KONFIGURATION: +# conf/-.conf +# Erwartete Variablen darin (alle optional, siehe Defaults unten): +# INTERVAL - Messintervall in Sekunden +# LINE_SPEED_IN_MBIT - Download-Kapazitaet der Leitung in Mbit/s +# LINE_SPEED_OUT_MBIT - Upload-Kapazitaet der Leitung in Mbit/s +# +# LOGS: +# Liegen unter /var/log/traffic-peak-monitor/ (wird beim Start +# automatisch angelegt, falls nicht vorhanden). Pro Interface gibt es +# eine AKTIVE Log-Datei ohne Datumsendung, z.B.: +# /var/log/traffic-peak-monitor/traffic-peak-monitor-lan4.log +# Sobald ein neuer Kalendertag beginnt, wird diese Datei mit dem Datum +# des Tages, zu dem ihre Eintraege gehoeren, umbenannt (= "rotiert"), +# z.B. in: +# /var/log/traffic-peak-monitor/traffic-peak-monitor-lan4.log.2026-08-03 +# Danach wird wieder in eine frische, aktive Log-Datei geschrieben. +# +# BERECHTIGUNGEN: +# Das Script muss als root (UID 0) laufen. Ein "sudo" ist dafuer nicht +# noetig, wenn es bereits als root gestartet wird (z.B. per systemd +# oder root-Crontab). + +set -u + +# Locale fuer Zahlenformate fest auf "C" setzen: printf's %f-Format +# richtet sich sonst nach der System-Locale und erwartet dort z.B. bei +# deutschen Locales ein Komma statt eines Punkts als Dezimaltrennzeichen. +# awk liefert die Prozentwerte weiter unten aber immer mit Punkt - ohne +# dieses LC_NUMERIC=C wuerde printf das mit "Ungueltige Zahl" ablehnen. +export LC_NUMERIC=C + +# --- Grundlegende Pfade ermitteln -------------------------------------- +# realpath loest auch Symlinks auf, damit das Script von ueberall aus +# aufgerufen werden kann (z.B. per systemd mit vollem Pfad) und trotzdem +# sein eigenes Verzeichnis korrekt findet. +script_name="$(basename "$(realpath "$0")")" +working_dir="$(dirname "$(realpath "$0")")" +conf_dir="${working_dir}/conf" + +# Feste Log-Basis unter /var/log - unabhaengig vom Script-Verzeichnis, +# damit Logs an der ueblichen Stelle fuer Systemd-Dienste liegen und +# z.B. von logrotate/Backup-Tools leichter gefunden werden. +log_dir="/var/log/traffic-peak-monitor" + +# Basisname ohne Endung, z.B. "traffic-peak-monitor" aus +# "traffic-peak-monitor.sh" - wird fuer Config- und Log-Dateinamen +# gebraucht. +base_name="${script_name%%.*}" + +# Log-Verzeichnis anlegen, falls es noch nicht existiert (inkl. evtl. +# fehlender Elternverzeichnisse, "-p" macht das automatisch und meldet +# auch keinen Fehler, falls es schon existiert) +mkdir -p "$log_dir" + +# --- Sicherheitscheck: muss als root laufen ---------------------------- +if [ "$(id -u)" -ne 0 ]; then + echo "Fehler: Dieses Script muss als root (UID 0) laufen." >&2 + exit 1 +fi + +# ======================================================================== +# WORKER: ueberwacht genau ein Interface dauerhaft +# ======================================================================== +run_worker() { + local IFACE=$1 + local conf_file="${conf_dir}/${base_name}-${IFACE}.conf" + local log_file="${log_dir}/${base_name}-${IFACE}.log" + + # Default-Werte, falls in der Konfigurationsdatei nicht gesetzt + local INTERVAL=2 + local LINE_SPEED_IN_MBIT=100 + local LINE_SPEED_OUT_MBIT=100 + + # Konfigurationsdatei einlesen - ueberschreibt die obigen Defaults + # mit den Werten aus der .conf Datei (einfaches "source", da die + # Config-Datei nur Variablenzuweisungen wie in einem Bash-Script + # enthaelt, z.B. LINE_SPEED_IN_MBIT=250) + if [ -f "$conf_file" ]; then + # shellcheck disable=SC1090 + source "$conf_file" + else + echo "Warnung: Konfigurationsdatei $conf_file nicht gefunden, nutze Default-Werte." >&2 + fi + + # Leitungskapazitaet von Mbit/s in kbit/s umrechnen, damit die Einheiten + # beim spaeteren Prozent-Vergleich zusammenpassen + local LINE_SPEED_IN_KBIT=$(( LINE_SPEED_IN_MBIT * 1000 )) + local LINE_SPEED_OUT_KBIT=$(( LINE_SPEED_OUT_MBIT * 1000 )) + + # Erste Messung als Ausgangsbasis + local PREV_RX PREV_TX MAX_RX MAX_TX CUR_HOUR HOUR_START HOUR_END CUR_DAY + PREV_RX=$(cat "/sys/class/net/${IFACE}/statistics/rx_bytes") + PREV_TX=$(cat "/sys/class/net/${IFACE}/statistics/tx_bytes") + MAX_RX=0 + MAX_TX=0 + CUR_HOUR=$(date +%H) + HOUR_START=$(date '+%Y-%m-%d %H:00') + HOUR_END=$(date -d '+1 hour' '+%H:00') + + # CUR_DAY merkt sich, zu welchem Kalendertag die aktuell gesammelten + # Daten (und damit die aktive, noch nicht rotierte Log-Datei) gehoeren. + CUR_DAY=$(date '+%Y-%m-%d') + + # Haupt-Schleife: laeuft dauerhaft, bis der Prozess beendet wird + while true; do + sleep "$INTERVAL" + local RX TX RX_RATE TX_RATE NOW_HOUR + RX=$(cat "/sys/class/net/${IFACE}/statistics/rx_bytes") + TX=$(cat "/sys/class/net/${IFACE}/statistics/tx_bytes") + + # Differenz * 8 = Byte -> Bit, / INTERVAL = Bit pro Sekunde + RX_RATE=$(( (RX - PREV_RX) * 8 / INTERVAL )) + TX_RATE=$(( (TX - PREV_TX) * 8 / INTERVAL )) + + [ "$RX_RATE" -gt "$MAX_RX" ] && MAX_RX=$RX_RATE + [ "$TX_RATE" -gt "$MAX_TX" ] && MAX_TX=$TX_RATE + + NOW_HOUR=$(date +%H) + if [ "$NOW_HOUR" != "$CUR_HOUR" ]; then + local MAX_RX_KBIT MAX_TX_KBIT RX_PCT TX_PCT + MAX_RX_KBIT=$(( MAX_RX / 1000 )) + MAX_TX_KBIT=$(( MAX_TX / 1000 )) + RX_PCT=$(awk -v v="$MAX_RX_KBIT" -v c="$LINE_SPEED_IN_KBIT" 'BEGIN{printf "%.1f", (v/c)*100}') + TX_PCT=$(awk -v v="$MAX_TX_KBIT" -v c="$LINE_SPEED_OUT_KBIT" 'BEGIN{printf "%.1f", (v/c)*100}') + + # Eintrag fuer die gerade abgeschlossene Stunde in die AKTIVE + # Log-Datei schreiben. Wichtig: das muss VOR einer moeglichen + # Tages-Rotation passieren, da dieser Eintrag noch zu CUR_DAY + # gehoert (z.B. der Eintrag "23:00-00:00" gehoert noch zum alten Tag). + # + # Feste Feldbreiten fuer eine sauber ausgerichtete Ausgabe: + # %7d -> kbit/s-Wert, rechtsbuendig, 7 Stellen breit. + # 7 Stellen reichen bis 9.999.999 kbit/s (= 9999 Mbit/s), + # deckt also auch 1000-Mbit/s-Leitungen (max. 1.000.000 + # kbit/s = 7-stellig) komfortabel ab. + # %5.1f -> Prozentwert, rechtsbuendig, 1 Nachkommastelle, + # 5 Stellen breit (deckt bis "100.0" ab). + # Durch die feste Breite des peak_rx-Blocks beginnt "peak_tx=" + # in jeder Zeile automatisch an derselben Spalte (linksbuendig), + # unabhaengig davon wie gross die einzelnen Zahlen sind. + printf '%s peak_rx=%7dkbit/s (%5.1f%%) peak_tx=%7dkbit/s (%5.1f%%)\n' \ + "${HOUR_START}-${HOUR_END}" "$MAX_RX_KBIT" "$RX_PCT" "$MAX_TX_KBIT" "$TX_PCT" >> "$log_file" + + MAX_RX=0 + MAX_TX=0 + CUR_HOUR=$NOW_HOUR + HOUR_START=$(date '+%Y-%m-%d %H:00') + HOUR_END=$(date -d '+1 hour' '+%H:00') + + # --- Tages-Rotation pruefen --------------------------------------- + # Hat sich der Kalendertag geaendert (z.B. Uebergang 23:xx -> 00:xx)? + # Falls ja: die bisherige aktive Log-Datei bekommt als Endung das + # Datum des Tages, dessen Eintraege sie enthaelt (CUR_DAY, also der + # ALTE Tag - nicht der gerade begonnene). Anschliessend beginnt eine + # neue, leere aktive Log-Datei fuer den neuen Tag. + local NEW_DAY + NEW_DAY=$(date '+%Y-%m-%d') + if [ "$NEW_DAY" != "$CUR_DAY" ]; then + if [ -f "$log_file" ]; then + mv "$log_file" "${log_file}.${CUR_DAY}" + fi + CUR_DAY=$NEW_DAY + fi + fi + + PREV_RX=$RX + PREV_TX=$TX + done +} + +# ======================================================================== +# LAUNCHER: kein Parameter angegeben -> alle Konfigurationen suchen +# und je einen Worker-Prozess starten +# ======================================================================== +if [ $# -eq 0 ]; then + # nullglob sorgt dafuer, dass das Array leer bleibt, wenn keine + # passenden Dateien existieren (statt des woertlichen Musters) + shopt -s nullglob + conf_files=("${conf_dir}/${base_name}"-*.conf) + shopt -u nullglob + + if [ ${#conf_files[@]} -eq 0 ]; then + echo "Keine Konfigurationsdateien in ${conf_dir} gefunden (erwartet: ${base_name}-.conf)" >&2 + exit 1 + fi + + pids=() + for cf in "${conf_files[@]}"; do + # Interface-Namen aus dem Dateinamen herausschneiden: + # aus "traffic-peak-monitor-lan4.11.conf" wird "lan4.11" + cf_base=$(basename "$cf" .conf) + iface="${cf_base#${base_name}-}" + + echo "Starte Monitoring fuer Interface '${iface}' (Konfiguration: ${cf})" + # Script ruft sich selbst im Worker-Modus auf, im Hintergrund. + # stdout/stderr des Worker-Prozesses gehen in eine eigene .out Datei, + # damit unerwartete Fehler (z.B. falscher Interface-Name) auffindbar sind. + "$0" "$iface" >> "${log_dir}/${base_name}-${iface}.out" 2>&1 & + pids+=("$!") + done + + echo "Gestartete Worker-Prozesse (PIDs): ${pids[*]}" + + # "wait" haelt den Launcher-Prozess am Leben, solange mindestens ein + # Worker laeuft. Das ist wichtig, falls der Launcher selbst z.B. per + # systemd ueberwacht werden soll (siehe systemd-Unit) - ohne "wait" + # wuerde der Launcher sofort beendet sein, obwohl die Worker im + # Hintergrund weiterlaufen. + wait + exit 0 +fi + +# ======================================================================== +# WORKER-MODUS: Interface als Parameter uebergeben +# ======================================================================== +run_worker "$1"