#!/usr/bin/env bash # status.sh # Author: Nils Knieling and Contributors- https://github.com/Cyclenerd/static_status # Simple Bash script to generate a status page. ME=$(basename "$0") BASE_PATH=$(dirname "$0") MY_TIMESTAMP=$(date -u "+%s") MY_LASTRUN_TIME="0" BE_LOUD="no" BE_QUIET="no" ################################################################################ # Usage ################################################################################ function usage { returnCode="$1" echo -e "Usage: $ME [OPTION]: OPTION is one of the following: \\t silent no output from faulty connections to stout (default: $BE_QUIET) \\t loud output from successful and faulty connections to stout (default: $BE_LOUD) \\t debug displays all variables \\t help displays help (this message)" exit "$returnCode" } case "$1" in "") # called without arguments ;; "silent") BE_QUIET="yes" ;; "loud") BE_LOUD="yes" ;; "debug") ONLY_OUTPUT_DEBUG_VARIABLES="yes" ;; "h" | "help" | "-h" | "-help" | "-?" | *) usage 0 ;; esac ################################################################################ #### Configuration Section ################################################################################ # Tip: You can also outsource configuration to an extra configuration file. # Just create a file named 'config' at the location of this script. # You can find an example here: # https://github.com/Cyclenerd/static_status/blob/master/config-example # You can also pass a configuration file with the variable MY_STATUS_CONFIG. # if a config file has been specified with MY_STATUS_CONFIG=myfile use this one, otherwise default to config if [[ -z "$MY_STATUS_CONFIG" ]]; then MY_STATUS_CONFIG="$BASE_PATH/config" fi if [ -e "$MY_STATUS_CONFIG" ]; then if [[ "$BE_LOUD" = "yes" ]] || [[ "$BE_QUIET" = "no" ]]; then echo "using config from file: $MY_STATUS_CONFIG" fi # ignore SC1090 # shellcheck source=/dev/null source "$MY_STATUS_CONFIG" fi # Tip: You can tweak curl parameters via .curlrc config file. # The default curl config file is checked for in the following places in this order: # 1. "$CURL_HOME/.curlrc" # 2. "$HOME/.curlrc" # # ~~~ Example .curlrc file ~~~ # # this is a comment # # change the useragent string # -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0" # # ok if certification validation fails # --insecure # ~~~ End of example file ~~~ # Title for the status page MY_STATUS_TITLE=${MY_STATUS_TITLE:-"Status Page"} # Link for the homepage button MY_HOMEPAGE_URL=${MY_HOMEPAGE_URL:-"https://github.com/Cyclenerd/static_status"} # Text for the homepage button MY_HOMEPAGE_TITLE=${MY_HOMEPAGE_TITLE:-"Homepage"} # Auto refresh interval in seconds 0 is no refresh MY_AUTOREFRESH=${MY_AUTOREFRESH:-"0"} # Shortcut to place the configuration file in a folder. # Save it without / at the end. MY_STATUS_CONFIG_DIR=${MY_STATUS_CONFIG_DIR:-"$HOME/status"} # List with the configuration. What do we want to monitor? MY_HOSTNAME_FILE=${MY_HOSTNAME_FILE:-"$MY_STATUS_CONFIG_DIR/status_hostname_list.txt"} # Where should the HTML status page be stored? MY_STATUS_HTML=${MY_STATUS_HTML:-"$HOME/status_index.html"} # Where should the SVG status icon be stored? MY_STATUS_ICON=${MY_STATUS_ICON-"$HOME/status.svg"} # Icon colors MY_STATUS_ICON_COLOR_SUCCESS=${MY_STATUS_ICON_COLOR_SUCCESS:-"lime"} MY_STATUS_ICON_COLOR_WARNING=${MY_STATUS_ICON_COLOR_WARNING:-"orange"} MY_STATUS_ICON_COLOR_DANGER=${MY_STATUS_ICON_COLOR_DANGER:-"red"} # Where should the JSON status page be stored? Set to "" to disable JSON output MY_STATUS_JSON=${MY_STATUS_JSON-"$HOME/status.json"} # Text file in which you can place a status message. # If the file exists and has a content, all errors on the status page are overwritten. MY_MAINTENANCE_TEXT_FILE=${MY_MAINTENANCE_TEXT_FILE:-"$MY_STATUS_CONFIG_DIR/status_maintenance_text.txt"} # Text file in which you can place notifications of past maintenance work. MY_PAST_MAINTENANCE_TEXT_FILE=${MY_PAST_MAINTENANCE_TEXT_FILE:-"$MY_STATUS_CONFIG_DIR/status_past_maintenance_text.txt"} # Duration we wait for response (nc, curl and traceroute). MY_TIMEOUT=${MY_TIMEOUT:-"2"} # Duration we wait for response (only ping). MY_PING_TIMEOUT=${MY_PING_TIMEOUT:-"4"} MY_PING_COUNT=${MY_PING_COUNT:-"2"} # Duration we wait for response (only script) MY_SCRIPT_TIMEOUT=${MY_SCRIPT_TIMEOUT:-20} # Route to host MY_TRACEROUTE_HOST=${MY_TRACEROUTE_HOST-"1.1.1.1"} # Cloudflare DNS # Sets the number of probe packets per hop MY_TRACEROUTE_NQUERIES=${MY_TRACEROUTE_NQUERIES:-"1"} # Location for the status files. Please do not edit created files. MY_HOSTNAME_STATUS_OK=${MY_HOSTNAME_STATUS_OK:-"$MY_STATUS_CONFIG_DIR/status_hostname_ok.txt"} MY_HOSTNAME_STATUS_DOWN=${MY_HOSTNAME_STATUS_DOWN:-"$MY_STATUS_CONFIG_DIR/status_hostname_down.txt"} MY_HOSTNAME_STATUS_LASTRUN=${MY_HOSTNAME_STATUS_LASTRUN:-"$MY_STATUS_CONFIG_DIR/status_hostname_last.txt"} MY_HOSTNAME_STATUS_DEGRADE=${MY_HOSTNAME_STATUS_DEGRADE:-"$MY_STATUS_CONFIG_DIR/status_hostname_degrade.txt"} MY_HOSTNAME_STATUS_LASTRUN_DEGRADE=${MY_HOSTNAME_STATUS_LASTRUN_DEGRADE:-"$MY_STATUS_CONFIG_DIR/status_hostname_last_degrade.txt"} MY_HOSTNAME_STATUS_HISTORY=${MY_HOSTNAME_STATUS_HISTORY:-"$MY_STATUS_CONFIG_DIR/status_hostname_history.txt"} MY_HOSTNAME_STATUS_HISTORY_TEMP_SORT=${MY_HOSTNAME_STATUS_HISTORY_TEMP_SORT:-"/tmp/status_hostname_history_sort.txt"} # Minimum downtime in seconds to display in past incidents MY_MIN_DOWN_TIME=${MY_MIN_DOWN_TIME:-"60"} # CSS Stylesheet for the status page MY_STATUS_STYLESHEET=${MY_STATUS_STYLESHEET:-"https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css"} # FontAwesome for the status page MY_STATUS_FONTAWESOME=${MY_STATUS_FONTAWESOME:-"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css"} # A footer MY_STATUS_FOOTER=${MY_STATUS_FOOTER:-'Powered by static_status'} # Lock file to prevent duplicate execution. # If this file exists, status.sh script is terminated. # If something has gone wrong and the file has not been deleted automatically, you can delete it. MY_STATUS_LOCKFILE=${MY_STATUS_LOCKFILE:-"/tmp/STATUS_SH_IS_RUNNING.lock"} # Date format for the web page. # UTC (`-u`) is the default. # Example: 2021-12-23 12:34:55 UTC MY_DATE_TIME=${MY_DATE_TIME:-$(date -u "+%Y-%m-%d %H:%M:%S %Z")} # Can be changed. Example with system time: # MY_DATE_TIME=$(date "+%Y-%m-%d %H:%M:%S") # Avoid semicolons. # More details can be found in `man date`. # Hook to call when a hostname status changes # The hook script must be executable and receives three arguments: # 1. New status, either up, down or degraded # 2. Command used # 3. Hostname MY_HOOK_STATUS=${MY_HOOK_STATUS:-""} ################################################################################ #### END Configuration Section ################################################################################ ################################################################################ # Helper ################################################################################ # debug_variables() print all script global variables to ease debugging debug_variables() { echo "USER: $USER" echo "SHELL: $SHELL" echo "BASH_VERSION: $BASH_VERSION" echo echo "MY_COMMANDS:" for MY_COMMAND in "${MY_COMMANDS[@]}"; do echo " $MY_COMMAND" done echo echo "MY_TIMEOUT: $MY_TIMEOUT" echo "MY_STATUS_CONFIG: $MY_STATUS_CONFIG" echo "MY_STATUS_CONFIG_DIR: $MY_STATUS_CONFIG_DIR" echo "MY_HOSTNAME_FILE: $MY_HOSTNAME_FILE" echo "MY_HOSTNAME_STATUS_OK: $MY_HOSTNAME_STATUS_OK" echo "MY_HOSTNAME_STATUS_DOWN: $MY_HOSTNAME_STATUS_DOWN" echo "MY_HOSTNAME_STATUS_LASTRUN: $MY_HOSTNAME_STATUS_LASTRUN" echo "MY_HOSTNAME_STATUS_DEGRADE: $MY_HOSTNAME_STATUS_DEGRADE" echo "MY_HOSTNAME_STATUS_LASTRUN_DEGRADE: $MY_HOSTNAME_STATUS_LASTRUN_DEGRADE" echo "MY_HOSTNAME_STATUS_HISTORY: $MY_HOSTNAME_STATUS_HISTORY" echo echo "MY_STATUS_HTML: $MY_STATUS_HTML" echo "MY_STATUS_ICON: $MY_STATUS_ICON" echo "MY_STATUS_JSON: $MY_STATUS_JSON" echo "MY_MAINTENANCE_TEXT_FILE: $MY_MAINTENANCE_TEXT_FILE" echo "MY_PAST_MAINTENANCE_TEXT_FILE: $MY_PAST_MAINTENANCE_TEXT_FILE" echo "MY_HOMEPAGE_URL: $MY_HOMEPAGE_URL" echo "MY_HOMEPAGE_TITLE: $MY_HOMEPAGE_TITLE" echo "MY_STATUS_TITLE: $MY_STATUS_TITLE" echo "MY_STATUS_STYLESHEET: $MY_STATUS_STYLESHEET" echo "MY_STATUS_FOOTER: $MY_STATUS_FOOTER" echo echo "MY_STATUS_LOCKFILE: $MY_STATUS_LOCKFILE" echo echo "MY_TIMEOUT: $MY_TIMEOUT" echo "MY_PING_TIMEOUT: $MY_PING_TIMEOUT" echo "MY_PING_COUNT: $MY_PING_COUNT" echo "MY_SCRIPT_TIMEOUT: $MY_SCRIPT_TIMEOUT" echo "MY_TRACEROUTE_HOST: $MY_TRACEROUTE_HOST" echo "MY_TRACEROUTE_NQUERIES: $MY_TRACEROUTE_NQUERIES" echo echo "MY_TIMESTAMP: $MY_TIMESTAMP" echo "MY_DATE_TIME: $MY_DATE_TIME" echo "MY_LASTRUN_TIME: $MY_LASTRUN_TIME" echo echo "MY_HOOK_STATUS: $MY_HOOK_STATUS" } # command_exists() tells if a given command exists. function command_exists() { command -v "$1" >/dev/null 2>&1 } # check_bash() check if current shell is bash function check_bash() { if [[ "$0" == *"bash" ]]; then exit_with_failure "Your current shell is $0" fi } # check_command() check if command exists and exit if not exists function check_command() { if ! command_exists "$1"; then exit_with_failure "Command '$1' not found" fi } # check_config() check if the configuration file is readable function check_config() { if [ ! -r "$1" ]; then exit_with_failure "Can not read required configuration file '$1'" fi } # check_file() check if the file exists if not create the file function check_file() { if [ ! -f "$1" ]; then if ! echo > "$1"; then exit_with_failure "Can not create file '$1'" fi fi if [ ! -w "$1" ]; then exit_with_failure "Can not write file '$1'" fi } # exit_with_failure() outputs a message before exiting the script. function exit_with_failure() { echo echo "FAILURE: $1" echo debug_variables echo del_lock exit 1 } # echo_warning() outputs a warning message. function echo_warning() { echo echo "WARNING: $1, will attempt to continue..." echo } # echo_do_not_edit() outputs a "do not edit" message to write to a file function echo_do_not_edit() { echo "#" echo "# !!! Do not edit this file !!!" echo "#" echo "# To reset everything, delete the files:" echo "# $MY_HOSTNAME_STATUS_OK" echo "# $MY_HOSTNAME_STATUS_DOWN" echo "# $MY_HOSTNAME_STATUS_LASTRUN" echo "# $MY_HOSTNAME_STATUS_DEGRADE" echo "# $MY_HOSTNAME_STATUS_LASTRUN_DEGRADE" echo "# $MY_HOSTNAME_STATUS_HISTORY" echo "#" } # set_lock() sets lock file function set_lock() { if ! echo "$MY_DATE_TIME" > "$MY_STATUS_LOCKFILE"; then exit_with_failure "Can not create lock file '$MY_STATUS_LOCKFILE'" fi } # del_lock() deletes lock file function del_lock() { rm "$MY_STATUS_LOCKFILE" &> /dev/null } # check_lock() checks lock file and exit if the file exists function check_lock() { if [ -f "$MY_STATUS_LOCKFILE" ]; then exit_with_failure "$ME is already running. Please wait... In case of problems simply delete the file: '$MY_STATUS_LOCKFILE'" fi } # port_to_name() outputs name of well-known ports # https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports function port_to_name() { case "$1" in 32[0-9][0-9]) MY_PORT_NAME="SAP Dispatcher" ;; 33[0-9][0-9]) MY_PORT_NAME="SAP Gateway" ;; 80[0-9][0-9]) MY_PORT_NAME="SAP ICM HTTP" ;; 443[0-9][0-9]) MY_PORT_NAME="SAP ICM HTTPS" ;; 36[0-9][0-9]) MY_PORT_NAME="SAP Message Server" ;; 5[0-9][0-9]00) MY_PORT_NAME="SAP J2EE HTTP" ;; 5[0-9][0-9]01) MY_PORT_NAME="SAP J2EE HTTPS" ;; 5[0-9][0-9]04) MY_PORT_NAME="SAP P4" ;; 5[0-9][0-9]08) MY_PORT_NAME="SAP Telnet" ;; *) MY_SERVICE_NAME=$(awk '$2 ~ /^'"$1"'\// {print $1; exit}' "/etc/services" 2> /dev/null) if [ -n "$MY_SERVICE_NAME" ]; then MY_PORT_NAME=$(echo "$MY_SERVICE_NAME" | awk '{print toupper($0)}') else MY_PORT_NAME="Port $1" fi ;; esac printf "%s" "$MY_PORT_NAME" } # get_lastrun_time() function get_lastrun_time() { while IFS=';' read -r MY_LASTRUN_COMMAND MY_LASTRUN_TIMESTAMP || [[ -n "$MY_LASTRUN_COMMAND" ]]; do if [[ "$MY_LASTRUN_COMMAND" = "timestamp" ]]; then if [ "$MY_LASTRUN_TIMESTAMP" -ge "0" ]; then MY_LASTRUN_TIME="$((MY_TIMESTAMP-MY_LASTRUN_TIMESTAMP))" else MY_LASTRUN_TIME="0" fi fi done <"$MY_HOSTNAME_STATUS_LASTRUN" } # check_downtime() check whether a failure has already been documented # and determine the duration function check_downtime() { MY_COMMAND="$1" MY_HOSTNAME="$2" MY_PORT="$3" MY_DOWN_TIME="0" while IFS=';' read -r MY_DOWN_COMMAND MY_DOWN_HOSTNAME MY_DOWN_PORT MY_PREVIOUS_DOWN_TIME || [[ -n "$MY_DOWN_COMMAND" ]]; do if [[ "$MY_DOWN_COMMAND" = "ping" ]] || [[ "$MY_DOWN_COMMAND" = "ping6" ]] || [[ "$MY_DOWN_COMMAND" = "nc" ]] || [[ "$MY_DOWN_COMMAND" = "grep" ]] || [[ "$MY_DOWN_COMMAND" = "traceroute" ]] || [[ "$MY_DOWN_COMMAND" = "curl" ]] || [[ "$MY_DOWN_COMMAND" = "http-status" ]] || [[ "$MY_DOWN_COMMAND" = "script" ]]; then if [[ "$MY_DOWN_HOSTNAME" = "$MY_HOSTNAME" ]]; then if [[ "$MY_DOWN_PORT" = "$MY_PORT" ]]; then MY_DOWN_TIME="$((MY_PREVIOUS_DOWN_TIME+MY_LASTRUN_TIME))" break # Skip entire rest of loop. fi fi fi done <"$MY_HOSTNAME_STATUS_LASTRUN" # MY_HOSTNAME_STATUS_DOWN is copied to MY_HOSTNAME_STATUS_LASTRUN } # check_degradetime() check whether a degradation has already been documented # and determine the duration function check_degradetime() { MY_COMMAND="$1" MY_HOSTNAME="$2" MY_DEGRADE_TIME="0" while IFS=';' read -r MY_DEGRADE_COMMAND MY_DEGRADE_HOSTNAME MY_PREVIOUS_DEGRADE_TIME || [[ -n "$MY_DEGRADE_COMMAND" ]]; do if [[ "$MY_DEGRADE_COMMAND" = "script" ]]; then if [[ "$MY_DEGRADE_HOSTNAME" = "$MY_HOSTNAME" ]]; then MY_DEGRADE_TIME="$((MY_PREVIOUS_DEGRADE_TIME+MY_LASTRUN_TIME))" break # Skip entire rest of loop. fi fi done <"$MY_HOSTNAME_STATUS_LASTRUN_DEGRADE" # MY_HOSTNAME_STATUS_DEGRADE is copied to MY_HOSTNAME_STATUS_LASTRUN_DEGRADE } # save_downtime() function save_downtime() { MY_COMMAND="$1" MY_HOSTNAME="$2" MY_PORT="$3" MY_DOWN_TIME="$4" printf "\\n%s;%s;%s;%s" "$MY_COMMAND" "$MY_HOSTNAME" "$MY_PORT" "$MY_DOWN_TIME" >> "$MY_HOSTNAME_STATUS_DOWN" if [[ "$BE_LOUD" = "yes" ]] || [[ "$BE_QUIET" = "no" ]]; then printf "\\n%-5s %-4s %s" "DOWN:" "$MY_COMMAND" "$MY_HOSTNAME" if [[ $MY_COMMAND == "nc" ]]; then printf " %s" "$(port_to_name "$MY_PORT")" fi if [[ $MY_COMMAND == "grep" ]]; then printf " %s" "$MY_PORT" fi if [[ $MY_COMMAND == "http-status" ]]; then printf " %s" "$MY_PORT" fi fi if [[ -x "${MY_HOOK_STATUS}" ]] && ! grep -E "^${MY_COMMAND};${MY_HOSTNAME}" "${MY_HOSTNAME_STATUS_LASTRUN}" &> /dev/null; then ${MY_HOOK_STATUS} "down" "${MY_COMMAND}" "${MY_HOSTNAME}" &> /dev/null fi } # save_degradetime() function save_degradetime() { MY_COMMAND="$1" MY_HOSTNAME="$2" MY_DEGRADE_TIME="$3" printf "\\n%s;%s;%s" "$MY_COMMAND" "$MY_HOSTNAME" "$MY_DEGRADE_TIME" >> "$MY_HOSTNAME_STATUS_DEGRADE" if [[ "$BE_LOUD" = "yes" ]] || [[ "$BE_QUIET" = "no" ]]; then printf "\\n%-5s %-4s %s" "DEGRADED:" "$MY_COMMAND" "$MY_HOSTNAME" fi if [[ -x "${MY_HOOK_STATUS}" ]] && ! grep -E "^${MY_COMMAND};${MY_HOSTNAME}" "${MY_HOSTNAME_STATUS_LASTRUN_DEGRADE}" &>/dev/null; then ${MY_HOOK_STATUS} "degraded" "${MY_COMMAND}" "${MY_HOSTNAME}" &> /dev/null fi } # save_availability() function save_availability() { MY_COMMAND="$1" MY_HOSTNAME="$2" MY_PORT="$3" printf "\\n%s;%s;%s" "$MY_COMMAND" "$MY_HOSTNAME" "$MY_PORT" >> "$MY_HOSTNAME_STATUS_OK" if [[ "$BE_LOUD" = "yes" ]]; then printf "\\n%-5s %-4s %s" "UP:" "$MY_COMMAND" "$MY_HOSTNAME" if [[ $MY_COMMAND == "nc" ]]; then printf " %s" "$(port_to_name "$MY_PORT")" fi if [[ $MY_COMMAND == "grep" ]]; then printf " %s" "$MY_PORT" fi if [[ $MY_COMMAND == "http-status" ]]; then printf " %s" "$MY_PORT" fi fi if [[ -x "${MY_HOOK_STATUS}" ]]; then if grep -E "^${MY_COMMAND};${MY_HOSTNAME}" "${MY_HOSTNAME_STATUS_LASTRUN}" &>/dev/null || grep -E "^${MY_COMMAND};${MY_HOSTNAME}" "${MY_HOSTNAME_STATUS_LASTRUN_DEGRADE}" &>/dev/null; then ${MY_HOOK_STATUS} "up" "${MY_COMMAND}" "${MY_HOSTNAME}" &> /dev/null fi fi } # save_history() function save_history() { MY_COMMAND="$1" MY_HOSTNAME="$2" MY_PORT="$3" MY_DOWN_TIME="$4" MY_DATE_TIME="$5" if cp "$MY_HOSTNAME_STATUS_HISTORY" "$MY_HOSTNAME_STATUS_HISTORY_TEMP_SORT" &> /dev/null; then printf "\\n%s;%s;%s;%s;%s" "$MY_COMMAND" "$MY_HOSTNAME" "$MY_PORT" "$MY_DOWN_TIME" "$MY_DATE_TIME" > "$MY_HOSTNAME_STATUS_HISTORY" cat "$MY_HOSTNAME_STATUS_HISTORY_TEMP_SORT" >> "$MY_HOSTNAME_STATUS_HISTORY" rm "$MY_HOSTNAME_STATUS_HISTORY_TEMP_SORT" &> /dev/null else exit_with_failure "Can not copy file '$MY_HOSTNAME_STATUS_HISTORY' to '$MY_HOSTNAME_STATUS_HISTORY_TEMP_SORT'" fi if [[ "$BE_LOUD" = "yes" ]]; then printf "\\n%-5s %-4s %s %s sec" "HIST:" "$MY_COMMAND" "$MY_HOSTNAME" "$MY_DOWN_TIME" if [[ $MY_COMMAND == "nc" ]]; then printf " %s" "$(port_to_name "$MY_PORT")" fi if [[ $MY_COMMAND == "grep" ]]; then printf " %s" "$MY_PORT" fi if [[ $MY_COMMAND == "http-status" ]]; then printf " %s" "$MY_PORT" fi fi } ################################################################################ # HTML ################################################################################ function page_header() { # check for autorefresh if [ "$MY_AUTOREFRESH" -gt 0 ] then MY_AUTOREFRESH_TEXT="" else MY_AUTOREFRESH_TEXT="" fi cat > "$MY_STATUS_HTML" << EOF $MY_STATUS_TITLE $MY_AUTOREFRESH_TEXT

$MY_STATUS_TITLE

$MY_HOMEPAGE_TITLE
EOF } function page_footer() { cat >> "$MY_STATUS_HTML" << EOF
EOF } function page_alert_success() { cat >> "$MY_STATUS_HTML" << EOF EOF } function page_alert_warning() { cat >> "$MY_STATUS_HTML" << EOF EOF } function page_alert_danger() { cat >> "$MY_STATUS_HTML" << EOF EOF } function page_alert_maintenance() { cat >> "$MY_STATUS_HTML" << EOF
Maintenance $MY_DATE_TIME
EOF if [ -r "$MY_MAINTENANCE_TEXT_FILE" ]; then cat "$MY_MAINTENANCE_TEXT_FILE" >> "$MY_STATUS_HTML" else echo ":-(" >> "$MY_STATUS_HTML" echo_warning "Can not read file '$MY_MAINTENANCE_TEXT_FILE'" fi cat >> "$MY_STATUS_HTML" << EOF
EOF } function page_past_maintenance() { cat >> "$MY_STATUS_HTML" << EOF

Past Maintenance

EOF if [ -r "$MY_PAST_MAINTENANCE_TEXT_FILE" ]; then cat "$MY_PAST_MAINTENANCE_TEXT_FILE" >> "$MY_STATUS_HTML" else echo ":-(" >> "$MY_STATUS_HTML" echo_warning "Can not read file '$MY_PAST_MAINTENANCE_TEXT_FILE'" fi cat >> "$MY_STATUS_HTML" << EOF
EOF } function item_ok() { echo '
  • ' if [[ -n "${MY_DISPLAY_TEXT}" ]]; then echo "${MY_DISPLAY_TEXT}" else if [[ "$MY_OK_COMMAND" = "ping" ]]; then echo "ping $MY_OK_HOSTNAME" elif [[ "$MY_OK_COMMAND" = "ping6" ]]; then echo "ping6 $MY_OK_HOSTNAME" elif [[ "$MY_OK_COMMAND" = "nc" ]]; then echo "$(port_to_name "$MY_OK_PORT") on $MY_OK_HOSTNAME" elif [[ "$MY_OK_COMMAND" = "curl" ]]; then echo "Site $MY_OK_HOSTNAME" elif [[ "$MY_OK_COMMAND" = "http-status" ]]; then echo "HTTP status $MY_OK_PORT of $MY_OK_HOSTNAME" elif [[ "$MY_OK_COMMAND" = "grep" ]]; then echo "Grep for \"$MY_OK_PORT\" on $MY_OK_HOSTNAME" elif [[ "$MY_OK_COMMAND" = "traceroute" ]]; then echo "Route path contains $MY_OK_HOSTNAME" elif [[ "$MY_OK_COMMAND" = "script" ]]; then echo "Script $MY_OK_HOSTNAME" fi fi cat <
  • EOF } function item_down() { echo '
  • ' if [[ -n "${MY_DISPLAY_TEXT}" ]]; then echo "${MY_DISPLAY_TEXT}" else if [[ "$MY_DOWN_COMMAND" = "ping" ]]; then echo "ping $MY_DOWN_HOSTNAME" elif [[ "$MY_DOWN_COMMAND" = "ping6" ]]; then echo "ping6 $MY_DOWN_HOSTNAME" elif [[ "$MY_DOWN_COMMAND" = "nc" ]]; then echo "$(port_to_name "$MY_DOWN_PORT") on $MY_DOWN_HOSTNAME" elif [[ "$MY_DOWN_COMMAND" = "curl" ]]; then echo "Site $MY_DOWN_HOSTNAME" elif [[ "$MY_DOWN_COMMAND" = "http-status" ]]; then echo "HTTP status $MY_DOWN_PORT of $MY_DOWN_HOSTNAME" elif [[ "$MY_DOWN_COMMAND" = "grep" ]]; then echo "Grep for \"$MY_DOWN_PORT\" on $MY_DOWN_HOSTNAME" elif [[ "$MY_DOWN_COMMAND" = "traceroute" ]]; then echo "Route path contains $MY_DOWN_HOSTNAME" elif [[ "$MY_DOWN_COMMAND" = "script" ]]; then echo "Script $MY_DOWN_HOSTNAME" fi fi printf ' ' if [[ "$MY_DOWN_TIME" -gt "1" ]]; then printf "%.0f min" "$((MY_DOWN_TIME/60))" else echo "" fi echo "
  • " } function item_degrade() { echo '
  • ' if [[ -n "${MY_DISPLAY_TEXT}" ]]; then echo "${MY_DISPLAY_TEXT}" else echo "Script $MY_DEGRADE_HOSTNAME" fi printf ' ' if [[ "$MY_DEGRADE_TIME" -gt "1" ]]; then printf "%.0f min" "$((MY_DEGRADE_TIME/60))" else echo "" fi echo "
  • " } function item_history() { echo '
  • ' echo '' if [[ -n "${MY_DISPLAY_TEXT}" ]]; then echo "${MY_DISPLAY_TEXT}" else if [[ "$MY_HISTORY_COMMAND" = "ping" ]]; then echo "ping $MY_HISTORY_HOSTNAME" elif [[ "$MY_HISTORY_COMMAND" = "ping6" ]]; then echo "ping6 $MY_HISTORY_HOSTNAME" elif [[ "$MY_HISTORY_COMMAND" = "nc" ]]; then echo "$(port_to_name "$MY_HISTORY_PORT") on $MY_HISTORY_HOSTNAME" elif [[ "$MY_HISTORY_COMMAND" = "curl" ]]; then echo "Site $MY_HISTORY_HOSTNAME" elif [[ "$MY_HISTORY_COMMAND" = "http-status" ]]; then echo "HTTP status $MY_HISTORY_PORT of $MY_HISTORY_HOSTNAME" elif [[ "$MY_HISTORY_COMMAND" = "grep" ]]; then echo "Grep for \"$MY_HISTORY_PORT\" on $MY_HISTORY_HOSTNAME" elif [[ "$MY_HISTORY_COMMAND" = "traceroute" ]]; then echo "Route path contains $MY_HISTORY_HOSTNAME" elif [[ "$MY_HISTORY_COMMAND" = "script" ]]; then echo "Script $MY_HISTORY_HOSTNAME" fi fi echo '' echo "$MY_HISTORY_DATE_TIME" echo '' echo '' printf ' ' if [[ "$MY_HISTORY_DOWN_TIME" -gt "1" ]]; then printf "%.0f min" "$((MY_HISTORY_DOWN_TIME/60))" else echo "" fi echo "
  • " } ################################################################################ # MAIN ################################################################################ check_bash # Commands we need MY_COMMANDS=( ping ping6 nc curl grep sed ) # Add traceroute optional if MY_TRACEROUTE_HOST is set if [[ -n "$MY_TRACEROUTE_HOST" ]]; then MY_COMMANDS+=("traceroute") fi if [[ -n "$ONLY_OUTPUT_DEBUG_VARIABLES" ]]; then debug_variables exit fi for MY_COMMAND in "${MY_COMMANDS[@]}"; do check_command "$MY_COMMAND" done check_lock set_lock check_config "$MY_HOSTNAME_FILE" check_file "$MY_HOSTNAME_STATUS_DOWN" check_file "$MY_HOSTNAME_STATUS_LASTRUN" check_file "$MY_HOSTNAME_STATUS_DEGRADE" check_file "$MY_HOSTNAME_STATUS_LASTRUN_DEGRADE" check_file "$MY_HOSTNAME_STATUS_HISTORY" check_file "$MY_HOSTNAME_STATUS_HISTORY_TEMP_SORT" check_file "$MY_STATUS_HTML" # Optional checks if [ -n "$MY_STATUS_ICON" ]; then check_file "$MY_STATUS_ICON" # status.svg fi if [ -n "$MY_STATUS_JSON" ]; then check_file "$MY_STATUS_JSON" # status.json fi if cp "$MY_HOSTNAME_STATUS_DOWN" "$MY_HOSTNAME_STATUS_LASTRUN" && cp "$MY_HOSTNAME_STATUS_DEGRADE" "$MY_HOSTNAME_STATUS_LASTRUN_DEGRADE"; then get_lastrun_time else exit_with_failure "Can not copy file '$MY_HOSTNAME_STATUS_DOWN' to '$MY_HOSTNAME_STATUS_LASTRUN' or '$MY_HOSTNAME_STATUS_DEGRADE' to '$MY_HOSTNAME_STATUS_LASTRUN_DEGRADE'" fi { echo "# $MY_DATE_TIME" echo_do_not_edit } > "$MY_HOSTNAME_STATUS_OK" { echo "# $MY_DATE_TIME" echo_do_not_edit echo "timestamp;$MY_TIMESTAMP" } > "$MY_HOSTNAME_STATUS_DEGRADE" { echo "# $MY_DATE_TIME" echo_do_not_edit echo "timestamp;$MY_TIMESTAMP" } > "$MY_HOSTNAME_STATUS_DOWN" # # Check and save status # MY_HOSTNAME_COUNT=0 while IFS=';' read -r MY_COMMAND MY_HOSTNAME_STRING MY_PORT || [[ -n "$MY_COMMAND" ]]; do MY_HOSTNAME="${MY_HOSTNAME_STRING%%|*}" # remove alternative display textS if [[ "$MY_COMMAND" = "ping" ]]; then (( MY_HOSTNAME_COUNT++ )) # Detect ping Version ping &> /dev/null # macOS: 64 = ping -n -t TIMEOUT # GNU: 2 = ping -n -w TIMEOUT (-t TTL) # OpenBSD: 1 = ping -n -w TIMEOUT (-t TTL) if [ $? -gt 2 ] || [[ "$OSTYPE" == "freebsd"* ]]; then # BSD ping MY_PING_COMMAND='ping -n -t' else # GNU or OpenBSD ping MY_PING_COMMAND='ping -n -w' fi if $MY_PING_COMMAND "$MY_PING_TIMEOUT" -c "$MY_PING_COUNT" "$MY_HOSTNAME" &> /dev/null; then check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" # Check status change if [[ "$MY_DOWN_TIME" -gt "0" ]]; then save_history "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" "$MY_DOWN_TIME" "$MY_DATE_TIME" fi save_availability "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" else check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" save_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" "$MY_DOWN_TIME" fi elif [[ "$MY_COMMAND" = "ping6" ]]; then (( MY_HOSTNAME_COUNT++ )) # Detect ping6 Version ping6 &> /dev/null # macOS: 64 = ping6 -n -t TIMEOUT # GNU: 2 = ping6 -n -w TIMEOUT (-t TTL) # OpenBSD: 1 = ping6 -n -w TIMEOUT (-t TTL) if [ $? -gt 2 ] || [[ "$OSTYPE" == "freebsd"* ]]; then # BSD ping6 MY_PING6_COMMAND='ping6 -n -t' else # GNU or OpenBSD ping6 MY_PING6_COMMAND='ping6 -n -w' fi if $MY_PING6_COMMAND "$MY_PING_TIMEOUT" -c "$MY_PING_COUNT" "$MY_HOSTNAME" &> /dev/null; then check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" # Check status change if [[ "$MY_DOWN_TIME" -gt "0" ]]; then save_history "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" "$MY_DOWN_TIME" "$MY_DATE_TIME" fi save_availability "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" else check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" save_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" "$MY_DOWN_TIME" fi elif [[ "$MY_COMMAND" = "nc" ]]; then (( MY_HOSTNAME_COUNT++ )) if nc -z -w "$MY_TIMEOUT" "$MY_HOSTNAME" "$MY_PORT" &> /dev/null; then check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" # Check status change if [[ "$MY_DOWN_TIME" -gt "0" ]]; then save_history "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" "$MY_DOWN_TIME" "$MY_DATE_TIME" fi save_availability "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" else check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" save_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" "$MY_DOWN_TIME" fi elif [[ "$MY_COMMAND" = "curl" ]]; then (( MY_HOSTNAME_COUNT++ )) if curl -If --max-time "$MY_TIMEOUT" "$MY_HOSTNAME" &> /dev/null; then check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" # Check status change if [[ "$MY_DOWN_TIME" -gt "0" ]]; then save_history "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" "$MY_DOWN_TIME" "$MY_DATE_TIME" fi save_availability "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" else check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" save_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "" "$MY_DOWN_TIME" fi elif [[ "$MY_COMMAND" = "http-status" ]]; then (( MY_HOSTNAME_COUNT++)) if [[ $(curl -s -o /dev/null -I --max-time "$MY_TIMEOUT" -w "%{http_code}" "$MY_HOSTNAME" 2>/dev/null) == "$MY_PORT" ]]; then check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" # Check status change if [[ "$MY_DOWN_TIME" -gt "0" ]]; then save_history "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" "$MY_DOWN_TIME" "$MY_DATE_TIME" fi save_availability "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" else check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" save_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" "$MY_DOWN_TIME" fi elif [[ "$MY_COMMAND" = "grep" ]]; then (( MY_HOSTNAME_COUNT++ )) if curl --no-buffer -fs --max-time "$MY_TIMEOUT" "$MY_HOSTNAME" | grep -q "$MY_PORT" &> /dev/null; then check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" # Check status change if [[ "$MY_DOWN_TIME" -gt "0" ]]; then save_history "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" "$MY_DOWN_TIME" "$MY_DATE_TIME" fi save_availability "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" else check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" save_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" "$MY_DOWN_TIME" fi elif [[ "$MY_COMMAND" = "traceroute" ]]; then (( MY_HOSTNAME_COUNT++ )) MY_PORT=${MY_PORT:=64} if traceroute -w "$MY_TIMEOUT" -q "$MY_TRACEROUTE_NQUERIES" -m "$MY_PORT" "$MY_TRACEROUTE_HOST" | grep -q "$MY_HOSTNAME" &> /dev/null; then check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" # Check status change if [[ "$MY_DOWN_TIME" -gt "0" ]]; then save_history "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" "$MY_DOWN_TIME" "$MY_DATE_TIME" fi save_availability "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" else check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" save_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" "$MY_DOWN_TIME" fi elif [[ "$MY_COMMAND" = "script" ]]; then (( MY_HOSTNAME_COUNT++ )) if [[ -x "$MY_STATUS_CONFIG_DIR/$MY_HOSTNAME" ]]; then MY_SCRIPT_COMMAND=("$MY_STATUS_CONFIG_DIR/$MY_HOSTNAME") elif [[ -x "$MY_HOSTNAME" ]]; then MY_SCRIPT_COMMAND=("$MY_HOSTNAME") else read -r -a MY_SCRIPT_COMMAND <<< "$MY_HOSTNAME" fi (timeout --preserve-status "$MY_SCRIPT_TIMEOUT" bash -c '"$@"' bash "${MY_SCRIPT_COMMAND[@]}" &> /dev/null) case "$?" in "0") check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" # Check status change if [[ "$MY_DOWN_TIME" -gt "0" ]]; then save_history "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" "$MY_DOWN_TIME" "$MY_DATE_TIME" fi save_availability "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" ;; "80") check_degradetime "$MY_COMMAND" "$MY_HOSTNAME_STRING" save_degradetime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_DEGRADE_TIME" ;; *) check_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" save_downtime "$MY_COMMAND" "$MY_HOSTNAME_STRING" "$MY_PORT" "$MY_DOWN_TIME" ;; esac fi done <"$MY_HOSTNAME_FILE" # # Create status page # page_header MY_ITEMS_JSON=() # Get outage MY_OUTAGE_COUNT=0 MY_OUTAGE_ITEMS=() while IFS=';' read -r MY_DOWN_COMMAND MY_DOWN_HOSTNAME_STRING MY_DOWN_PORT MY_DOWN_TIME || [[ -n "$MY_DOWN_COMMAND" ]]; do if [[ "$MY_DOWN_COMMAND" = "ping" ]] || [[ "$MY_DOWN_COMMAND" = "ping6" ]] || [[ "$MY_DOWN_COMMAND" = "nc" ]] || [[ "$MY_DOWN_COMMAND" = "curl" ]] || [[ "$MY_DOWN_COMMAND" = "http-status" ]] || [[ "$MY_DOWN_COMMAND" = "grep" ]] || [[ "$MY_DOWN_COMMAND" = "script" ]] || [[ "$MY_DOWN_COMMAND" = "traceroute" ]]; then MY_DOWN_HOSTNAME="${MY_DOWN_HOSTNAME_STRING%%|*}" MY_DISPLAY_TEXT="${MY_DOWN_HOSTNAME_STRING/${MY_DOWN_HOSTNAME}/}" MY_DISPLAY_TEXT="${MY_DISPLAY_TEXT:1}" (( MY_OUTAGE_COUNT++ )) MY_OUTAGE_ITEMS+=("$(item_down)") MY_ITEMS_JSON+=("${MY_DISPLAY_TEXT:-${MY_DOWN_HOSTNAME}};$MY_DOWN_COMMAND;Fail;$MY_DOWN_TIME") fi done <"$MY_HOSTNAME_STATUS_DOWN" # Get degrades MY_DEGRADE_COUNT=0 MY_DEGRADE_ITEMS=() while IFS=';' read -r MY_DEGRADE_COMMAND MY_DEGRADE_HOSTNAME_STRING MY_DEGRADE_TIME || [[ -n "$MY_DEGRADE_COMMAND" ]]; do if [[ "$MY_DEGRADE_COMMAND" = "script" ]]; then MY_DEGRADE_HOSTNAME="${MY_DEGRADE_HOSTNAME_STRING%%|*}" MY_DISPLAY_TEXT="${MY_DEGRADE_HOSTNAME_STRING/${MY_DEGRADE_HOSTNAME}/}" MY_DISPLAY_TEXT="${MY_DISPLAY_TEXT:1}" (( MY_DEGRADE_COUNT++ )) MY_DEGRADE_ITEMS+=("$(item_degrade)") MY_ITEMS_JSON+=("${MY_DISPLAY_TEXT:-${MY_DEGRADE_HOSTNAME}};$MY_DEGRADE_COMMAND;Degraded;$MY_DEGRADE_TIME") fi done <"$MY_HOSTNAME_STATUS_DEGRADE" # Get available systems MY_AVAILABLE_COUNT=0 MY_AVAILABLE_ITEMS=() while IFS=';' read -r MY_OK_COMMAND MY_OK_HOSTNAME_STRING MY_OK_PORT || [[ -n "$MY_OK_COMMAND" ]]; do if [[ "$MY_OK_COMMAND" = "ping" ]] || [[ "$MY_OK_COMMAND" = "ping6" ]] || [[ "$MY_OK_COMMAND" = "nc" ]] || [[ "$MY_OK_COMMAND" = "curl" ]] || [[ "$MY_OK_COMMAND" = "http-status" ]] || [[ "$MY_OK_COMMAND" = "grep" ]] || [[ "$MY_OK_COMMAND" = "script" ]] || [[ "$MY_OK_COMMAND" = "traceroute" ]]; then MY_OK_HOSTNAME="${MY_OK_HOSTNAME_STRING%%|*}" MY_DISPLAY_TEXT="${MY_OK_HOSTNAME_STRING/${MY_OK_HOSTNAME}/}" MY_DISPLAY_TEXT="${MY_DISPLAY_TEXT:1}" (( MY_AVAILABLE_COUNT++ )) MY_AVAILABLE_ITEMS+=("$(item_ok)") MY_ITEMS_JSON+=("${MY_DISPLAY_TEXT:-${MY_OK_HOSTNAME}};$MY_OK_COMMAND;OK;0") fi done <"$MY_HOSTNAME_STATUS_OK" MY_OUTAGED_AND_DEGRADE_COUNT=$((MY_OUTAGE_COUNT + MY_DEGRADE_COUNT)) # Maintenance text if [ -s "$MY_MAINTENANCE_TEXT_FILE" ]; then page_alert_maintenance # or status alert elif [[ "$MY_OUTAGE_COUNT" -gt "$MY_AVAILABLE_COUNT" ]]; then page_alert_danger elif [[ "$MY_OUTAGED_AND_DEGRADE_COUNT" -gt "0" ]]; then page_alert_warning else page_alert_success fi # Outage to HTML if [[ "$MY_OUTAGE_COUNT" -gt "0" ]]; then cat >> "$MY_STATUS_HTML" << EOF
    " >> "$MY_STATUS_HTML" fi # Degraded to HTML if [[ "$MY_DEGRADE_COUNT" -gt "0" ]]; then cat >> "$MY_STATUS_HTML" << EOF
    " >> "$MY_STATUS_HTML" fi # Operational to HTML if [[ "$MY_AVAILABLE_COUNT" -gt "0" ]]; then cat >> "$MY_STATUS_HTML" << EOF
    " >> "$MY_STATUS_HTML" fi # Outage and operational to SVG if [ -n "$MY_STATUS_ICON" ]; then MY_STATUS_ICON_COLOR="$MY_STATUS_ICON_COLOR_SUCCESS" if [[ "$MY_OUTAGE_COUNT" -gt "$MY_AVAILABLE_COUNT" ]]; then MY_STATUS_ICON_COLOR="$MY_STATUS_ICON_COLOR_DANGER" elif [[ "$MY_OUTAGE_COUNT" -gt "0" ]]; then MY_STATUS_ICON_COLOR="$MY_STATUS_ICON_COLOR_WARNING" fi printf '' "$MY_STATUS_ICON_COLOR" > "$MY_STATUS_ICON" fi # Outage and operational to JSON if [ -n "$MY_STATUS_JSON" ]; then printf "[\n" > "$MY_STATUS_JSON" for ((position = 0; position < ${#MY_ITEMS_JSON[@]}; ++position)); do IFS=";" read -r -a ITEMS <<< "${MY_ITEMS_JSON[$position]}" # shellcheck disable=SC2001 MY_OUTAGE_ITEM=$(sed -e 's/<[^>]*>//g' <<< "${ITEMS[0]}") MY_OUTAGE_ITEM_CMD="${ITEMS[1]}" MY_OUTAGE_ITEM_STATUS="${ITEMS[2]}" MY_OUTAGE_ITEM_TIME="${ITEMS[3]}" printf ' {\n "site": "%s",\n "command": "%s",\n "status": "%s",\n "time_sec": "%s",\n "updated": "%s"\n }' \ "$MY_OUTAGE_ITEM" "$MY_OUTAGE_ITEM_CMD" "$MY_OUTAGE_ITEM_STATUS" "$MY_OUTAGE_ITEM_TIME" "$MY_DATE_TIME" >> "$MY_STATUS_JSON" if [ "$position" -lt "$(( ${#MY_ITEMS_JSON[@]} - 1 ))" ]; then printf ",\n" >> "$MY_STATUS_JSON" else printf "\n" >> "$MY_STATUS_JSON" fi done printf "]" >> "$MY_STATUS_JSON" fi # Past maintenance text if [ -s "$MY_PAST_MAINTENANCE_TEXT_FILE" ]; then page_past_maintenance fi # Get history (last 10 incidents) MY_HISTORY_COUNT=0 MY_HISTORY_ITEMS=() MY_SHOW_INCIDENTS="false" while IFS=';' read -r MY_HISTORY_COMMAND MY_HISTORY_HOSTNAME_STRING MY_HISTORY_PORT MY_HISTORY_DOWN_TIME MY_HISTORY_DATE_TIME || [[ -n "$MY_HISTORY_COMMAND" ]]; do if [[ "$MY_HISTORY_DOWN_TIME" -ge "$MY_MIN_DOWN_TIME" ]]; then MY_SHOW_INCIDENTS="true" if [[ "$MY_HISTORY_COMMAND" = "ping" ]] || [[ "$MY_HISTORY_COMMAND" = "ping6" ]] || [[ "$MY_HISTORY_COMMAND" = "nc" ]] || [[ "$MY_HISTORY_COMMAND" = "curl" ]] || [[ "$MY_HISTORY_COMMAND" = "http-status" ]] || [[ "$MY_HISTORY_COMMAND" = "grep" ]] || [[ "$MY_HISTORY_COMMAND" = "script" ]] || [[ "$MY_HISTORY_COMMAND" = "traceroute" ]]; then MY_HISTORY_HOSTNAME="${MY_HISTORY_HOSTNAME_STRING%%|*}" MY_DISPLAY_TEXT="${MY_HISTORY_HOSTNAME_STRING/${MY_HISTORY_HOSTNAME}/}" MY_DISPLAY_TEXT="${MY_DISPLAY_TEXT:1}" (( MY_HISTORY_COUNT++ )) MY_HISTORY_ITEMS+=("$(item_history)") fi if [[ "$MY_HISTORY_COUNT" -gt "9" ]]; then break fi fi done <"$MY_HOSTNAME_STATUS_HISTORY" # History to HTML if [[ "$MY_SHOW_INCIDENTS" == "true" ]]; then cat >> "$MY_STATUS_HTML" << EOF

    Past Incidents

    " >> "$MY_STATUS_HTML" fi page_footer del_lock echo