Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 1080 lines (951 sloc) 48.7 KB
#!/bin/sh
#description: create static status pages
#usage: staticus [options]
#example:
#$ staticus -c ~/.staticus.conf --modules "memory,swap,load" -o status.html
###############################################################################
############################## Configuration ##################################
###############################################################################
report_html="./staticus.html"
report_txt="./staticus.txt"
modules="title,status,memory,swap,load,storage,process,info"
#modules="title,status,notification,memory,swap,load,storage,process,info"
#module's properties
module_title_msg="Staticus - $(hostname -f) $(date "+%d-%m-%Y %H:%M (%Z)")"
module_storage_partitions="/,/home"
module_process_list="init,rsyslogd,cron"
module_info_list="issue,uname,uptime"
module_notification_msg="Next maintenance window is programmed at Tuesday May 12th"
#thresholds
module_memory_threshold="80"
module_swap_threshold="80"
module_load_threshold="4"
module_storage_threshold="80"
#notifications
notify="false" #or true
notify_method="mailgun"
notify_contacts="admin@example.com,contact@example.com"
theme="default"
config_file="/etc/staticus.conf"
###############################################################################
VERSION="2017.06.20-12:08"
status_ok="0"
status_error="1"
status_warning="2"
themes="default"
theme_default='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'
_usage() {
printf "%s\\n" "Usage: ${progname} [options] -o staticus.html"
printf "%s\\n" "Create static status pages."
printf "\\n"
printf "%s\\n" " -c, --config /etc/staticus.conf configuration file"
printf "%s\\n" " -m, --modules \"all\" define modules"
printf "%s\\n" " -o, --output-html staticus.html html status output file"
printf "%s\\n" " -O, --output-txt staticus.txt txt status output file"
printf "%s\\n" " --txt2html staticus.txt convert txt to html"
printf "%s\\n" " --theme default use specified html theme"
printf "%s\\n" " --list-modules list available modules"
printf "%s\\n" " --list-themes list available html themes"
printf "\\n"
printf "%b\\n" " -U, --update update this program to latest version"
printf "%s\\n" " -v, --version display version"
printf "%s\\n" " -h, --help show this help message and exit"
}
_basename() {
[ -z "${1}" ] && return 1 || _basename__name="${1%%/}"
[ -z "${2}" ] || _basename__suffix="${2}"
case "${_basename__name}" in
/*|*/*) _basename__name="$(expr "${_basename__name}" : '.*/\([^/]*\)')" ;;
esac
if [ -n "${_basename__suffix}" ] && [ "${#_basename__name}" -gt "${#2}" ]; then
if [ X"$(printf "%s\\n" "${_basename__name}" | cut -c"$((${#_basename__name} - ${#_basename__suffix} + 1))"-"${#_basename__name}")" \
= X"$(printf "%s\\n" "${_basename__suffix}")" ]; then
_basename__name="$(printf "%s\\n" "${_basename__name}" | cut -c1-"$((${#_basename__name} - ${#_basename__suffix}))")"
fi
fi
printf "%s\\n" "${_basename__name}"
}
_update() {
_u__current_file="$(cd "$(dirname "${0}")" && pwd)/${progname}"
_u__current_version_long="$(awk -F\" \
'/VERSION=/{print $2;exit}' "${_u__current_file}" 2>/dev/null)"
_u__current_version="$(printf "%s\\n" "${_u__current_version_long}" | \
awk '{gsub(/[\.:]/,"");gsub(/-/,"");print;exit}' 2>/dev/null)"
[ -z "${_u__current_version}" ] && printf "%s\\n%s\\n%s\\n" \
"ERROR: Failed to detect current version, please update manually" \
"${progname} = ${_u__current_file}" \
"${progname} version = ${_u__current_version}" >&2 && return 1
command -v "wget" >/dev/null 2>&1 || command -v "curl" >/dev/null 2>&1 || \
{ printf "%s\\n" "ERROR: Install either 'wget' or 'curl' to upgrade" >&2; return 1; }
_u__url="https://raw.githubusercontent.com/javier-lopez/learn/master/sh/tools/${progname}"
_u__tmpfile="/tmp/${progname}.${$}.update"
_u__error_msg="$(wget -q -O- --no-check-certificate "${_u__url}" \
> "${_u__tmpfile}" 2>&1 || curl -s "${_u__url}" \
> "${_u__tmpfile}" 2>&1)" || { printf "%s\\n%s\\n" \
"ERROR: Failed to fetch update, please try later or update manually" \
"${_u__error_msg}" >&2; return 1; }
_u__update_version_long="$(awk -F\" \
'/VERSION=/{print $2;exit}' "${_u__tmpfile}" 2>/dev/null)"
_u__update_version="$(printf "%s" "${_u__update_version_long}" | awk \
'{gsub(/[\.:]/,"");gsub(/-/,"");print;exit}' 2>/dev/null)"
[ -n "${_u__update_version}" ] || _u__update_version="0"
if [ "${_u__current_version}" -lt "${_u__update_version}" ]; then
printf "%s %s\\n" "Updating from version" \
"${_u__current_version_long} to ${_u__update_version_long} ..."
chmod +x "${_u__tmpfile}"
if ! mv -f "${_u__tmpfile}" "${_u__current_file}" 2>/dev/null; then
printf "%s\\n" "ERROR: no write permissions on ${_u__current_file}" >&2
printf "%s\\n" "INFO : trying with sudo ..." >&2
if command -v "sudo" >/dev/null 2>&1; then
sudo mv "${_u__tmpfile}" "${_u__current_file}" || return 1
else
printf "%s\\n" "ERROR: sudo isn't available, exiting ..." >&2
rm -rf "${_u__tmpfile}"
return 1
fi
fi
printf "%s %s\\n" "${progname} is up-to-date (${_u__update_version_long})"
return 0
fi
printf "%s %s\\n" "${progname} is up-to-date (${_u__current_version_long})"
rm -rf "${_u__tmpfile}"
}
_show_version() {
printf "%s\\n" "${progname} ${VERSION}"
}
_die() {
[ -z "${1}" ] || printf "%s\\n" "${*}" >&2
_usage >&2; exit 1
}
_warning() {
[ -z "${1}" ] || printf "%s\\n" "${*}" >&2
}
_normalize_file() {
printf "%s\\n" "${@}" | sed 's:-:/dev/stdout:'
}
_file_is_writable() {
case "${1}" in
'/dev/stdout'|'/dev/stderr') return 0 ;;
*)
printf "%s\\n" "writable" > "${1}" 2>/dev/null
test "$(cat "${1}" 2>/dev/null)" = "writable" || return 1
esac
}
_decode64() {
[ ! -t 0 ] && set -- "${@}" "$(cat)"
[ -z "${1}" ] && return 1
if command -v "base64" >/dev/null 2>&1; then
printf "%s\\n" "${@}" | base64 -d
elif command -v "openssl" >/dev/null 2>&1; then
printf "%s\\n" "${@}" | openssl enc -base64 -d
elif command -v "awk" >/dev/null 2>&1 && (command -v "uudecode" || command -v "busybox") >/dev/null 2>&1; then
if command -v "uudecode" >/dev/null 2>&1; then
uudecode__bin="uudecode"
elif command -v "busybox" >/dev/null 2>&1; then
uudecode__bin="busybox uudecode"
fi
_decode64_awk() { [ ! -t 0 ] && set -- "${@}" "$(cat)"
[ -z "${1}" ] && return 1
printf "%s\\n" "${@}" | sed 's/=//g' | (
printf "begin 644 -\\n"; awk 'function _decode64_awk() {
inp=1; out=""; while (getline) { for(i=1; i<=length($0); i++) {
c=substr(uu,index(b64,substr($0,i,1)),1);
inp++; out=(out c); if (inp==61) {
print "M" out; inp=1; out=""; }}}
if (length(out)) { printf "%c", (32+3*length(out)/4); print out; }}
BEGIN { b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
uu="`!\"#$%&'\''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
_decode64_awk(); exit; }'
printf "%s\\n%s\\n" '`' 'end' #'
) | $uudecode__bin
}
printf "%s\\n" "${@}" | _decode64_awk
else
_decode64_sh() { [ ! -t 0 ] && set -- "${@}" "$(cat)"
_decode64_sh__b64='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
_decode64_sh__n="0"; _decode64_sh__v="0"; _decode64_sh__args="$@"
while [ "${_decode64_sh__args}" ]; do #process char by char
_decode64_sh__char="${_decode64_sh__args%${_decode64_sh__args#?}}"
case "${_decode64_sh__char}" in
'\n') continue ;;
'=') _decode64_sh__v="$(($_decode64_sh__v << 6))" ;;
*) _decode64_sh__char="${_decode64_sh__b64#*$_decode64_sh__char}"
_decode64_sh__char="$((${#_decode64_sh__b64}-${#_decode64_sh__char}))"
if [ "${_decode64_sh__char}" -eq "0" ]; then
[ X"${_decode64_sh__args}" = X"${_decode64_sh__char}" ] &&\
_decode64_sh__args='' || _decode64_sh__args="${_decode64_sh__args#?}"
continue
fi
_decode64_sh__v="$(($_decode64_sh__v << 6 | $_decode64_sh__char-1))"
esac
_decode64_sh__n="$(($_decode64_sh__n+1))"
if [ "${_decode64_sh__n}" -eq "4" ]; then
_decode64_sh__s="16"; while [ "${_decode64_sh__s}" -gt "-1" ]; do
_decode64_sh__char="$(($_decode64_sh__v >> $_decode64_sh__s & 255))"
printf \\$(($_decode64_sh__char/64*100+$_decode64_sh__char%64/8*10+$_decode64_sh__char%8))
_decode64_sh__s="$(($_decode64_sh__s-8))"
done
_decode64_sh__v="0"; _decode64_sh__n="0"
fi
[ X"${_decode64_sh__args}" = X"${_decode64_sh__char}" ] &&\
_decode64_sh__args='' || _decode64_sh__args="${_decode64_sh__args#?}"
done
}
printf "%s\\n" "${@}" | _decode64_sh
fi
} # too hardcore for vim syntax`"
_str2lower() {
[ -z "${1}" ] && return 1
printf "%s\\n" "${@}" | \
tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'
# tr '[:upper:]' '[:lower:]'
}
_str2upper() {
[ -z "${1}" ] && return 1
printf "%s\\n" "${@}" | \
tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
# tr '[:upper:]' '[:lower:]'
}
_bytes2human() {
[ -z "${1}" ] && return 1
#is int?
case "${1%.*}" in
*[!0-9]*|"") return 1 ;;
esac
printf "%s\\n" "${1}" | awk '{
split( "bytes Kb Mb Gb Tb Eb Pb Yb Zb" , v );
s=1; while($1>=1024) { $1/=1024; s++ }
printf("%.2f %s\n", $1, v[s])}' | sed 's:\.00 : :'
}
_loadconf() {
#$1 => config file
[ ! -f "${1}" ] && return 1
_loadconf__options=$(awk '! /export/ {if ($0 ~ "^.*=[^;&]*" && $0 !~ "&&" && $1 !~ "^#") print }' "${1}")
eval "${_loadconf__options}"
}
_escape_special_characters() {
#http://stackoverflow.com/questions/407523/escape-a-string-for-a-sed-replace-pattern
sed -e 's/[]\/$*.^|[]/\\&/g'
}
_staticus_report_module() {
[ -z "${2}" ] && return 1
_srm__module="${1}"
_srm__module_status="${2}"
_srm__module_msg="${3}"
case "$(_str2lower "${_srm__module}")" in
title)
printf "%s\\n" "# ${_srm__module}: ${_srm__module_status}"
;;
status)
printf "%s\\n" "## ${_srm__module}: ${_srm__module_status}"
;;
notification)
printf "%s\\n" "### ${_srm__module}: ${2}"
;;
*)
printf "\\n%s\\n" "#### ${_srm__module}: ${2}"
;;
esac
if [ -n "${_srm__module_msg}" ]; then
printf "%s\\n" "${_srm__module_msg}"
fi
}
_module_title() {
[ -z "${1}" ] && return 1
_staticus_report_module "title" "${*}"
}
_module_notification() {
[ -z "${1}" ] && return 1
_staticus_report_module "notification" "notification" "${*}"
}
_module_memory() {
[ -z "${1}" ] && return 1
#https://bugzilla.redhat.com/show_bug.cgi?id=1253036
_mmemory__input="$(free -k | grep Mem)"
_mmemory__total="$(printf "%s\\n" "${_mmemory__input}" | awk '{print $2}')"
_mmemory__used="$(printf "%s\\n" "${_mmemory__input}" | awk '{print $3}')"
_mmemory__used_percentage="$(printf "%s\\n" "${_mmemory__input}" | awk '{printf "%.2f", $3/$2 * 100.0}' | cut -d\. -f1)"
_mmemory__threshold="$(printf "%s\\n" "${_mmemory__total} ${1}" | awk '{printf "%.2f", $1 * ($2/100)}' | cut -d\. -f1)"
_mmemory__description="$(printf "%s\\n%s\\n%s\\n" \
"* threshold $(_bytes2human "$(($_mmemory__threshold*1024))") (${1}%)" \
"* current $(_bytes2human "$(($_mmemory__used*1024))") (${_mmemory__used_percentage}%)" \
"* total $(_bytes2human "$(($_mmemory__total*1024))")")"
if [ "${_mmemory__used_percentage}" -ge "${1}" ]; then
_staticus_report_module "memory" "warning" "${_mmemory__description}"
return "${status_warning}"
else
_staticus_report_module "memory" "ok" "${_mmemory__description}"
fi
}
_module_swap() {
[ -z "${1}" ] && return 1
#https://bugzilla.redhat.com/show_bug.cgi?id=1253036
_mswap__input="$(free -k | grep Swap)"
_mswap__total="$(printf "%s\\n" "${_mswap__input}" | awk '{print $2}')"
_mswap__used="$(printf "%s\\n" "${_mswap__input}" | awk '{print $3}')"
_mswap__description="$(printf "%s\\n%s\\n" "* no swap configured" " ${_mswap__input}")"
if [ X"${_mswap__total}" = X"0" ]; then
_staticus_report_module "swap" "error" "${_mswap__description}"
return "${status_error}"
fi
_mswap__used_percentage="$(printf "%s\\n" "${_mswap__input}" | awk '{printf "%.2f", $3/$2 * 100.0}' | cut -d\. -f1)"
_mswap__threshold="$(printf "%s\\n" "${_mswap__total} ${1}" | awk '{printf "%.2f", $1 * ($2/100)}' | cut -d\. -f1)"
_mswap__description="$(printf "%s\\n%s\\n%s\\n" \
"* threshold $(_bytes2human "$(($_mswap__threshold*1024))") (${1}%)" \
"* current $(_bytes2human "$(($_mswap__used*1024))") (${_mswap__used_percentage}%)" \
"* total $(_bytes2human "$(($_mswap__total*1024))")")"
if [ "${_mswap__used_percentage}" -ge "${1}" ]; then
_staticus_report_module "swap" "warning" "${_mswap__description}"
return "${status_warning}"
else
_staticus_report_module "swap" "ok" "${_mswap__description}"
fi
}
_module_load() {
[ -z "${1}" ] && return 1
_mload__input="$(awk '{print $1}' /proc/loadavg 2>&1)" || {
_staticus_report_module "load" "error" "${_mload__input}"
return "${status_error}"
}
_mload__used_percentage="$(printf "%s\\n" "${_mload__input} ${1}" | \
awk '{printf "%.2f", ($1 * 100.0) / $2}' | cut -d\. -f1)"
_mload__description="$(printf "%s\\n%s\\n%s\\n" \
"* threshold ${1}" \
"* current ${_mload__input} (${_mload__used_percentage}%)")"
if [ "${_mload__input%.*}" -ge "${1}" ]; then
_staticus_report_module "load" "warning" "${_mload__description}"
return "${status_warning}"
else
_staticus_report_module "load" "ok" "${_mload__description}"
fi
}
_module_storage() {
[ -z "${2}" ] && return 1
_mstorage__input="$(df -P 2>&1)" || {
_staticus_report_module "storage" "error" "${_mstorage__input}"
return "${status_error}"
}
_mstorage__status="${status_ok}"
_mstorage__OLDIFS="${IFS}"
IFS=","; for partition in ${2}; do
_mstorage__partition="$(printf "%s\\n" "${_mstorage__input}" | grep "${partition}$")"
if [ -z "${_mstorage__partition}" ]; then
_staticus_report_module "storage ${partition}" "error" "* partition ${partition} doesn't exists"
continue;
fi
_mstorage__total="$(printf "%s\\n" "${_mstorage__partition}" | awk '{print $2}')"
_mstorage__used="$(printf "%s\\n" "${_mstorage__partition}" | awk '{print $3}')"
_mstorage__used_percentage="$(printf "%s\\n" "${_mstorage__partition}" | awk '{gsub("%",""); print $5}')"
_mstorage__threshold="$(printf "%s\\n" "${_mstorage__total} ${1}" | awk '{printf "%.2f", $1 * ($2/100)}' | cut -d\. -f1)"
#df outputs numbers in Kb, convert them to bytes
_mstorage__used="$(($_mstorage__used*1024))"
_mstorage__total="$(($_mstorage__total*1024))"
_mstorage__threshold="$(($_mstorage__threshold*1024))"
_mstorage__description="$(printf "%s\\n%s\\n%s\\n" \
"* threshold $(_bytes2human "${_mstorage__threshold}") (${1}%)" \
"* current $(_bytes2human "${_mstorage__used}") (${_mstorage__used_percentage}%)" \
"* total $(_bytes2human "${_mstorage__total}")")"
if [ "${_mstorage__used_percentage}" -ge "${1}" ]; then
_staticus_report_module "storage ${partition}" "warning" "${_mstorage__description}"
_mstorage__status="${status_warning}"
else
_staticus_report_module "storage ${partition}" "ok" "${_mstorage__description}"
fi
done; IFS="${_mstorage__OLDIFS}"
return "${_mstorage__status}"
}
_module_process() {
[ -z "${1}" ] && return 1
_mprocess__input="$(ps aux 2>&1)" || {
_staticus_report_module "process" "error" "${_mprocess__input}"
return 1
}
_mprocess__status="${status_ok}"
_mprocess__OLDIFS="${IFS}"
IFS=","; for process in ${1}; do
_mprocess__name="$(printf "%s\\n" "${_mprocess__input}" | awk '/'"${process}"'/ {print; exit}')"
_mprocess__detailed="$(printf "%s\\n" "${_mprocess__name}" | \
awk '{print "cpu:", $3 "%", "mem:", $4 "%s", "user:", $1, "cmd:", substr($0, index($0,$11)); exit}')"
_mprocess__description="$(printf "%s\\n" "* ${_mprocess__detailed}")"
if [ -z "${_mprocess__name}" ]; then
_mprocess__description="$(printf "%s\\n" "* process isn't running")"
_staticus_report_module "process ${process}" "warning" "${_mprocess__description}"
_mprocess__status="${status_warning}"
else
_staticus_report_module "process ${process}" "ok" "${_mprocess__description}"
fi
done; IFS="${_mprocess__OLDIFS}"
return "${_mprocess__status}"
}
_module_info() {
_module_info_column() {
#get titles
_minfoc__description="${1}"
_minfoc__description_titles="$(printf "%s\\n" "${1}" | awk '/^\*/{printf "%s ", $2}')"
#find largest title len
_minfoc__OLDIFS="${IFS}"; _minfoc__description_title_size_max="0"
IFS=" "; for _minfoc__description_title in ${_minfoc__description_titles}; do
_minfoc__description_title_size="${#_minfoc__description_title}"
if [ "${_minfoc__description_title_size}" -gt "${_minfoc__description_title_size_max}" ]; then
_minfoc__description_title_size_max="${_minfoc__description_title_size}"
fi
done; IFS="${_minfoc__OLDIFS}"
#append whitespaces to titles
_minfoc__OLDIFS="${IFS}"
IFS=" "; for _minfoc__description_title in ${_minfoc__description_titles}; do
_minfoc__description_new_title="${_minfoc__description_title}"
_minfoc__description_new_title_size="${#_minfoc__description_new_title}"
while [ "${_minfoc__description_new_title_size}" -lt "${_minfoc__description_title_size_max}" ]; do
_minfoc__description_new_title="${_minfoc__description_new_title} "
_minfoc__description_new_title_size="${#_minfoc__description_new_title}"
done
_minfoc__description="$(printf "%s\\n" "${_minfoc__description}" | \
sed "s:${_minfoc__description_title}:${_minfoc__description_new_title}:")"
done; IFS="${_minfoc__OLDIFS}"
#return formated data
printf "%s\\n" "${_minfoc__description}"
}
_minfo__OLDIFS="${IFS}"
IFS=","; for info in ${1}; do
case "${info}" in
issue)
_minfo__issue="* /etc/issue $(cat /etc/issue.net)"
_minfo__description="${_minfo__description}${_minfo__issue}\n"
;;
uname)
_minfo__uname="* uname $(uname -snvp)"
_minfo__description="${_minfo__description}${_minfo__uname}\n"
;;
uptime)
_minfo__uptime="* uptime $(uptime | awk '{sub(/,/," hours"); printf $3" "$4}')"
_minfo__description="${_minfo__description}${_minfo__uptime}\n"
;;
esac
done; IFS="${_minfo__OLDIFS}"
#apply new lines to the description, fix this, it should be added in the
#above case statements
_minfo__description="$(printf "%b\\n" "${_minfo__description}")"
#format output in a tabular form
_minfo__description=$(_module_info_column "${_minfo__description}")
_staticus_report_module "info" "info" "${_minfo__description}"
}
_module_status() {
[ -z "${1}" ] && return 1
if [ "${1}" -lt "1" ]; then
_staticus_report_module "status" "ok" "Everything is running ok"
else
_staticus_report_module "status" "error" "There are ${1} issues"
fi
}
_staticus_notify() {
# $1 => title msg
# $2 => body msg
[ -z "${3}" ] && return 1
_staticus_notify_mailgun() {
if command -v "mailgun" >/dev/null; then
for contact in ${notify_contacts}; do
contact="$(printf "%s\\n" "${contact}" | sed "s:#%#:@:")"
mailgun --subject "${progname} - $(hostname -f): ${1}" "${contact}" "$(
printf "+---Notification----------------------------+\\n"
printf "%b\\n" "${2}"
printf "+-------------------------------------------+\\n"
)" >/dev/null || return 1
done
else
_warning "mailgun is not available, install it to use this notification module"
_warning "https://raw.githubusercontent.com/javier-lopez/learn/master/sh/tools/mailgun"
return 1
fi
}
_snotify__module="${1}"; shift
_snotify__type="${1}"; shift
printf "%b\\n%b\\n" "${_snotify__module} - ${_snotify__type}" "${*}" >&2
case "$(_str2lower "${notify_method}")" in
mailgun) _staticus_notify_"${notify_method}" "${_snotify__module}" "${_snotify__type}" "${*}" ;;
*) return 1;;
esac
}
_inflate_theme() {
# $1 => theme
# $2 => report_html
eval "_itheme__b64=\$theme_${1}"
_itheme__tmpdir="$(mktemp -d)" || return 1
( cd "${_itheme__tmpdir}" && printf "%s\\n" "${_itheme__b64}" | _decode64 | zcat | tar xvf - >/dev/null ) || \
{ rm -rf "${_itheme__tmpdir}"; return 1; }
for _itheme__template in "${_itheme__tmpdir}"/*; do
[ -f "${_itheme__template}" ] || return 1
mv "${_itheme__template}" "${2}" && rm -rf "${_itheme__tmpdir}"
return 0
done
}
_staticus_txt2html() {
[ -z "${2}" ] && return 1
_stxt2html__report_txt="${1}"
_stxt2html__report_html="${2}"
_inflate_theme "${theme}" "${_stxt2html__report_html}" || return 1
_stxt2html__report_txt_content="$(cat "${_stxt2html__report_txt}")"
_stxt2html__report_html_content="$(cat "${_stxt2html__report_html}")"
#title section
_stxt2html__title="$(printf "%s\\n" "${_stxt2html__report_txt_content}" | \
awk '/^# title:/ {print substr($0, index($0,$3)); exit}' | \
_escape_special_characters)"
if [ -z "${_stxt2html__title}" ]; then
_warning "txt2html: no title was found, skipping..."
else
_stxt2html__report_html_content="$(printf "%s\\n" "${_stxt2html__report_html_content}" | \
sed "s/STATICUS_TITLE/${_stxt2html__title}/g")"
fi
#status section
_stxt2html__status="$(printf "%s\\n" "${_stxt2html__report_txt_content}" | \
awk '/^## status:/ {print substr($0, index($0,$3)); exit}' | \
_escape_special_characters)"
_stxt2html__status_description="$(printf "%s\\n" "${_stxt2html__report_txt_content}" | \
awk '/^## status:/ {getline;print;exit}' | _escape_special_characters)"
if [ -z "${_stxt2html__status}" ]; then
_warning "txt2html: no status was found, skipping..."
else
case "${_stxt2html__status}" in
ok) _stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | \
sed "s/STATICUS_EVERYTHING_OK/${_stxt2html__status_description}/g")" ;;
error) _stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | \
sed "s/STATICUS_FAILED_MODULES/${_stxt2html__status_description}/g")";;
esac
fi
#notification section
_stxt2html__notification="$(printf "%s\\n" "${_stxt2html__report_txt_content}" | \
awk '/^### notification:/ {print substr($0, index($0,$3)); exit}' | \
_escape_special_characters)"
_stxt2html__notification_description="$(printf "%s\\n" "${_stxt2html__report_txt_content}" | \
sed '0,/^### notification/d;/####/,$d' | sed '/^\s*$/d' | \
_escape_special_characters)"
if [ -n "${_stxt2html__notification}" ]; then
_stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | \
sed "s/STATICUS_NOTIFICATION/${_stxt2html__notification_description}/g")"
fi
#modules section
_stxt2html__modules="$(printf "%s\\n" "${_stxt2html__report_txt_content}" | awk '/^#### /')"
if [ -z "${_stxt2html__modules}" ]; then
_warning "txt2html: no modules were found, skipping..."
else
_stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | sed 's/STATICUS_MODULE_PLACEHOLDER//g')"
_stxt2html__OLDIFS="${IFS}"; IFS='
'; for _stxt2html__module in ${_stxt2html__modules}; do
_stxt2html__module_status="${_stxt2html__module##*:}"
_stxt2html__module_status="${_stxt2html__module##* }"
_stxt2html__module_escaped="$(printf "%s\\n" "${_stxt2html__module}" | \
_escape_special_characters)"
_stxt2html__module_description="$(printf "%s\\n" \
"${_stxt2html__report_txt_content}" | \
sed '1,/^'"${_stxt2html__module_escaped}"'/d;/####/,$d' | sed '/^\s*$/d')"
_stxt2html__module="$(printf "%s\\n" "${_stxt2html__module}" | \
awk -F: '{gsub("^#### ","");print $1}' | \
awk -F "" '{$1=toupper($1)}1' OFS=)"
#special info formatting
if [ "${_stxt2html__module}" = "Info" ]; then
_stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | sed 's/STATICUS_INFO_PLACEHOLDER//g')"
for _stxt2html__module_description_line in ${_stxt2html__module_description}; do
#remove extra white spaces, [ \t]
_stxt2html__module_description_line="$(printf "%s\\n" "${_stxt2html__module_description_line}" | awk '{$1=$1};1')"
_stxt2html__module_description_line="${_stxt2html__module_description_line#* }"
_stxt2html__module_info_cmd="${_stxt2html__module_description_line%% *}"
_stxt2html__module_info_description="${_stxt2html__module_description_line#* }"
_stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | \
awk '/STATICUS_INFO_DESCRIPTION/ {print;print;next}; 1')"
_stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | \
awk -v cmd="${_stxt2html__module_info_cmd}"\
-v description="${_stxt2html__module_info_description}" \
'/STATICUS_INFO_DESCRIPTION/ && !seen {
gsub(/STATICUS_INFO_CMD/, cmd);
gsub(/STATICUS_INFO_DESCRIPTION/, description);seen=1;print;next}; 1')"
done
else
_stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | \
awk '/module '"${_stxt2html__module_status}"'.*STATICUS_MODULE_DESCRIPTION/ {
print;print;next}; 1')"
_stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | \
awk -v module="${_stxt2html__module}" \
-v description="${_stxt2html__module_description}" \
'/module '"${_stxt2html__module_status}"'.*STATICUS_MODULE_DESCRIPTION/ && !seen {
gsub(/STATICUS_MODULE_NAME/, module);
gsub(/STATICUS_MODULE_DESCRIPTION/, description);seen=1;print;next}; 1')"
fi
done; IFS="${_stxt2html__OLDIFS}"
fi
#contacts section
if [ -z "${notify_contacts}" ]; then
_warning "txt2html: no contacts were found, skipping..."
else
_stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | sed 's/STATICUS_CONTACT_PLACEHOLDER//g')"
for _stxt2html__contact in ${notify_contacts}; do
_stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | \
awk '/mailto:STATICUS_CONTACT/ {print;print;next}; 1')"
_stxt2html__report_html_content="$(printf "%s\\n" \
"${_stxt2html__report_html_content}" | \
awk -v contact="${_stxt2html__contact}" \
'/mailto:STATICUS_CONTACT/ && !seen {
gsub(/STATICUS_CONTACT/, contact);seen=1;print;next}; 1')"
done
fi
#cleanup not used placeholders
_stxt2html__report_html_content="$(printf "%s\\n" "${_stxt2html__report_html_content}" | \
sed '/STATICUS_/d')"
#update IDs
_stxt2html__report_html_content="$(printf "%s\\n" "${_stxt2html__report_html_content}" | \
awk '/ID_/ {counter++; gsub(/ID_./, "ID_" counter ); print;next}; 1')"
#write final html report
printf "%s\\n" "${_stxt2html__report_html_content}" > "${_stxt2html__report_html}"
}
_staticus() {
#$1 => modules
#$2 => output file
[ -z "${2}" ] && return 1
OLDIFS="${IFS}"
IFS=","; for module in $(_str2lower "${1}"); do {
case "${module}" in
title) _module_title "${module_title_msg}" ;;
notification) _module_notification "${module_notification_msg}" ;;
memory) _module_memory "${module_memory_threshold}" ;;
swap) _module_swap "${module_swap_threshold}" ;;
load) _module_load "${module_load_threshold}" ;;
storage) _module_storage "${module_storage_threshold}" "${module_storage_partitions}" ;;
process) _module_process "${module_process_list}" ;;
info) _module_info "${module_info_list}";;
status) use_module_status="1" ;;
*) _warning "module ${module} doesn't exists, skipping..." ;;
esac } >> "${2}"
current_status="${?}"
if [ X"${current_status}" != X"0" ]; then
if [ -z "${failed_modules}" ]; then
failed_modules="${module}"
else
failed_modules="${failed_modules},${module}"
fi
fi
done; IFS="${OLDIFS}"
if [ -n "${use_module_status}" ]; then
if [ -n "${failed_modules}" ]; then
failed_modules_len=$(($(printf "%s\\n" "${failed_modules}" | tr -cd ',' | wc -c) + 1))
fi
_module_status "${failed_modules_len:-0}" >> "${2}"
#append to the next line after title
status_msg="$(sed -n '/^## status:/,$p' "${2}" 2>/dev/null | tr '\n' '\r')"
sed -i '/^## status:/,$d' "${2}"
sed -i "s/^# title:.*/&\n\n${status_msg}/" "${2}"
#and cleanup
sed -i "s/\r/\n/" "${2}"
sed -i "s/\r//" "${2}"
fi
return "${failed_modules_len:-0}"
}
progname="$(_basename "${0}")"
#use a temporal file to save data which eventually will become txt|html outputs
tmpfile="/tmp/${progname}.${$}.tmp"
trap "rm -f -- ${tmpfile}" 0 2 3 15 #remove it on exit|crashes|etc
if [ ! -t 0 ]; then
#there is input comming from pipe or file, add to the end of $@
set -- "${@}" $(cat)
fi
[ "${#}" -eq "0" ] && _die
for arg in "${@}"; do #parse options
case "${arg}" in
-h|--help) _usage && exit ;;
-U|--update) _update; exit "${?}" ;;
-v|--version) _show_version; exit "${?}" ;;
'-c'|'--config'|-c*|--config*)
case "${arg}" in
'-c'|'--config')
if [ "${#}" -gt "1" ]; then
case "${2}" in
-*) _die "Option '${arg}' requires a parameter" ;;
esac
shift; user_config_file="${1}"; [ "${1}" ] && shift
else
_die "Option '${arg}' requires a parameter"
fi
;;
-c*) user_config_file="${1#-c}"; shift ;;
--config*) user_config_file="${1#--config}"; shift ;;
esac
if [ -f "${user_config_file}" ]; then
if [ -r "${user_config_file}" ]; then
config_file="${user_config_file}"
else
_die "Specified config file '${user_config_file}' isn't readable"
fi
else
_die "Specified config file '${user_config_file}' doesn't exists"
fi
;;
'-m'|'--modules'|-m*|--modules*)
case "${arg}" in
'-m'|'--modules')
if [ "${#}" -gt "1" ]; then
case "${2}" in
-*) _die "Option '${arg}' requires a parameter" ;;
esac
shift; user_modules="${1}"; [ "${1}" ] && shift
else
_die "Option '${arg}' requires a parameter"
fi
;;
-m*) user_modules="${1#-m}"; shift ;;
--modules*) user_modules="${1#--modules}"; shift ;;
esac
case "${user_modules}" in
all) : ;;
*) modules="${user_modules}"
esac
;;
'-o'|'--output-html'|-o*|--output-html*)
case "${arg}" in
'-o'|'--output-html')
if [ "${#}" -gt "1" ]; then
case "${2}" in
-*) _die "Option '${arg}' requires a parameter" ;;
esac
shift; user_page_html="${1}"; [ "${1}" ] && shift
else
_die "Option '${arg}' requires a parameter"
fi
;;
-o*) user_page_html="${1#-o}"; shift ;;
--output-html*) user_page_html="${1#--output-html}"; shift ;;
esac
user_page_html_normalized="$(_normalize_file "${user_page_html}")"
if _file_is_writable "${user_page_html_normalized}"; then
report_html="${user_page_html_normalized}"
else
_die "Unable to write to '${user_page_html}' output file"
fi
;;
'-O'|'--output-txt'|-O*|--output-txt*)
case "${arg}" in
'-O'|'--output-txt')
if [ "${#}" -gt "1" ]; then
case "${2}" in
-*) _die "Option '${arg}' requires a parameter" ;;
esac
shift; user_page_txt="${1}"; [ "${1}" ] && shift
else
_die "Option '${arg}' requires a parameter"
fi
;;
-O*) user_page_txt="${1#-O}"; shift ;;
--output-txt*) user_page_txt="${1#--output-txt}"; shift ;;
esac
user_page_txt_normalized="$(_normalize_file "${user_page_txt}")"
if _file_is_writable "${user_page_txt_normalized}"; then
report_txt="${user_page_txt_normalized}"
else
_die "Unable to write to '${user_page_html}' output file"
fi
;;
--txt2html|--txt2html*)
case "${arg}" in
'--txt2html')
if [ "${#}" -gt "1" ]; then
case "${2}" in
-*) _die "Option '${arg}' requires a parameter" ;;
esac
shift; user_txt2html="${1}"; [ "${1}" ] && shift
else
_die "Option '${arg}' requires a parameter"
fi
;;
--txt2html*) user_txt2html="${1#--txt2html}"; shift ;;
esac
if [ -r "${user_txt2html}" ]; then
[ -f "${user_txt2html}" ] && report_txt="${user_txt2html}" || \
_die "Specified ${progname} file '${user_txt2html}' doesn't exists"
else
_die "Specified ${progname} file '${user_config_file}' isn't readable"
fi
;;
--theme|--theme*)
case "${arg}" in
'--theme')
if [ "${#}" -gt "1" ]; then
case "${2}" in
-*) _die "Option '${arg}' requires a parameter" ;;
esac
shift; user_theme="${1}"; [ "${1}" ] && shift
else
_die "Option '${arg}' requires a parameter"
fi
;;
--theme*) user_theme="${1#--theme}"; shift ;;
esac
if [ -z "$(printf "%s\\n" "${themes}" | tr ' ' '\n' | awk "/^$user_theme\$/")" ]; then
_warning "${progname}: '${user_theme}' is not a recognized theme, using default ..."
fi
;;
--list-modules) printf "%s\\n" "${modules}" | tr ',' '\n'; exit 0; ;;
--list-themes) printf "%s\\n" "${themes}" | tr ',' '\n'; exit 0; ;;
-*) _die "${progname}: unrecognized option '${arg}'" ;;
esac
done
_loadconf "${config_file}"
if [ -z "${user_txt2html}" ]; then
#report_txt could be /dev/stdout|/dev/stderr, so we better use a tmpfile
_staticus "${modules}" "${tmpfile}"
cat "${tmpfile}" > "${report_txt}"
_staticus_txt2html "${tmpfile}" "${report_html}" || return 1
if [ "$(_str2lower "${notify}")" = "true" ]; then
if [ -n "${failed_modules_len}" ]; then
_staticus_notify "There are ${failed_modules_len} issues" "$(cat "${tmpfile}")"
fi
fi
else
_staticus_txt2html "${report_txt}" "${report_html}"
fi
# vim:set ts=4 sw=4 tw=0 ft=sh :