diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/adei/adei.sh | 287 | ||||
-rw-r--r-- | lib/adei/adei_error.sh | 74 | ||||
-rw-r--r-- | lib/adei/adei_print.sh | 25 | ||||
-rw-r--r-- | lib/adei/adei_version.sh | 51 | ||||
-rw-r--r-- | lib/helpers.sh | 9 | ||||
-rwxr-xr-x | lib/nagios/nagios.sh | 125 | ||||
-rw-r--r-- | lib/remote/README.txt | 34 | ||||
-rw-r--r-- | lib/remote/print.sh | 168 | ||||
-rw-r--r-- | lib/remote/report.sh | 51 | ||||
-rw-r--r-- | lib/remote/run.sh | 13 | ||||
-rw-r--r-- | lib/remote/status.sh | 196 |
11 files changed, 1033 insertions, 0 deletions
diff --git a/lib/adei/adei.sh b/lib/adei/adei.sh new file mode 100644 index 0000000..3a0aeb6 --- /dev/null +++ b/lib/adei/adei.sh @@ -0,0 +1,287 @@ +cd $(dirname $0) + +MAX_SOURCE_OFFSET=3600 +MAX_MASTER_OFFSET=300 +MAX_SLAVE_OFFSET=300 + +adei_default_timeout=${default_timeout:-120} + +. lib/adei/adei_version.sh +. lib/adei/adei_print.sh +. lib/adei/adei_error.sh +. lib/nagios/nagios.sh + +shopt -s nocasematch; + +# Auth with redirect (-L/--location-trusted) not working. Credentials are lost on hops. +function adei_query { + local resp + local timeout=${3:-$adei_default_timeout} + + local err=0 + if [ "$2" == "ecode" ]; then + url="$1&mysql=master" +# resp=$(curl --proxy "" -f -m "$timeout" "$url" 2>&1 | grep "returned error") + resp=$(curl --proxy "" --location-trusted -sf -m "$timeout" -w "%{http_code}" -o /dev/null "$url" 2>&1); + [ -z "$resp" -o "$resp" = "000" ] && resp="10" # error code 1 + elif [ "$2" == "emsg" ]; then + url="$1&mysql=master" + resp=$(curl --proxy "" --location-trusted -f -m "$timeout" "$url" 2>&1 | grep -o "curl.*") + [ -z "$resp" ] && resp="No response from" + else + if [ "$2" == "slave" ]; then + url="$1&mysql=slave" + else + url="$1&mysql=master" + fi + + + resp=$(curl --proxy "" --location-trusted -sf -m "$timeout" "$url"); err=$? + if [ $err -ne 0 ]; then + resp=$(adei_query "$1" "ecode" "$timeout") + err=$(($(($resp / 10)) + $(($resp % 10)))) + + resp=$(adei_query "$1" "emsg" "$timeout") + + [ -n "$debug" ] && echo "$(date) $timeout Failed $url" >> /tmp/adei.log + else + [ -n "$debug" ] && echo "$(date) $timeout OK $url" >> /tmp/adei.log + fi + fi + + echo -n $resp + return $err +} + +function adei_format_query { + local with_auth="${1:-1}" + local query="$2" + local timeout=${3:-$adei_default_timeout} + local source=${4:-"$adei_source"} + local url="${5:-$adei_url}" + + auth="" + [ $with_auth -gt 0 ] && auth="$adei_auth" + if [[ "$query" =~ \? ]]; then + echo "http://${auth}${url}/${query}${source}" + else + echo "http://${auth}${url}/${query}?xxxxx${source}" + fi +} + +function adei_simple_query { + local req=$(adei_format_query 1 "$@") + adei_query "$req" "master" "$timeout"; err=$? + return $err +} + +function adei_text_query { + local out # Local on the same string breaks error reporting + out="$(adei_simple_query "$@")"; local err=$? + + if [ $err -gt 0 -o -z "$out" ]; then +# echo "Error sending ADEI request: $(adei_format_query 0 "$@")" + [ $err -eq 0 ] && local err=1 + [ -n "$out" ] && echo -n "$out" + return $err + elif [[ "$out" =~ "Error:" ]]; then + echo -n "$out" + return 7 + else + echo -n "$out" + return 0 + fi +} + +function adei_xml_query { + local out # Local on the same string breaks error reporting + out="$(adei_simple_query "$@")"; local err=$? + + if [ $err -ne 0 -o -z "$out" ]; then +# echo "Error sending ADEI request: $(adei_format_query 0 '$@')" + [ $err -eq 0 ] && err=1 + [ -n "$out" ] && echo "$out" + return $err + fi + + local xml="$(echo "$out" | xmllint --format - 2>/dev/null)" + if [ $err -ne 0 -o -z "$out" ]; then + echo "$out" + if [[ "$out" =~ "Error:" ]]; then + return 7 + else + return 4 + fi + fi + + error=$(echo "$xml" | grep "<Error>") + if [ -n "$error" ]; then + echo $error | sed -e "s|</\?Error>||g" + return 7 + fi + + echo "$xml" + return $err +} + +function adei_value_query { + local out # Local on the same string breaks error reporting + out="$(adei_xml_query "$@")"; local err=$? + [ $err -ne 0 ] && { echo "$out"; return $err; } + + local values + values="$(echo "$out" | grep "Value")"; err=$? + [ $err -ne 0 ] && return 6 + + echo "$values" +} + + +function adei_get_databases { + local out + out="$(adei_xml_query "list.php?target=databases" "$@")" + [ $err -gt 0 ] && { echo -n "$out"; return $err; } + echo "$out" | grep "Value" | sed -e "s/^.*db_name=\"\([^\"]*\)\".*$/\\1/" | sed -e "s/ /::space::/" +} + +function adei_query_version { + local version # Local on the same string breaks error reporting + + version="$(adei_text_query "info.php?target=version&encoding=text" "$@")"; local err=$? + [ $err -gt 0 ] && { echo "$version"; return $err; } + + adei_version="$version" + + adei_revision=$(echo $adei_version | cut -d '-' -f 1) + if [ "$adei_revision" == "$adei_version" ]; then + adei_date="" + else + adei_date=$(echo $adei_version | cut -d '-' -f 2) + fi +} + +function adei_resolve_id { + fn="$1" + id="$2" + host="$3" + setup="$4" + + local var=$(cat "$fn" | grep "^$id" | awk '{ print $2 }') + [ -z "$var" -a -n "$host" ] && var=$(cat "$fn" | grep "^$host" | awk '{ print $2 }') + [ -z "$var" -a -n "$setup" ] && var=$(cat "$fn" | grep "^$setup" | awk '{ print $2 }') + + [ -n "$debug" ] && echo "$(date) resolved ($var) from $fn (id=$id, host=$host, setup=$setup) pwd ($(pwd))" >> /tmp/resolv.log + echo "$var" +} + +function adei_init_ { + local id="$1" && shift # Either URL or [setup]@[host] +# local url="$1" && shift + local server="$1" && shift + local database="$1" && [[ ! "$server" =~ \&|= ]] && shift + adei_args=( "$@" ) + + [ -z "$id" ] && { echo "ADEI ID is not specified" && exit 8 ; } + + + local url + local host + local setup + if [[ $id =~ http.*:// ]]; then # url + url="$id" + host="$(echo ${url#http*://} | cut -d '/' -f 1)" # parse port, maybe + + unset $setup + elif [[ $id =~ : ]]; then # [setup@]host + local seho + IFS='@' read -ra seho <<< "$id" && shift + host="${seho[1]:-${seho[0]}}" # parse port, for sure + setup="${seho[1]:+${seho[0]}}" + + unset $url + else # [setup]@[host] or both, no port + local seho + IFS='@' read -ra seho <<< "$id" && shift # techincally we can try to resolve to decide which is which + + host="${seho[1]:-${seho[0]}}" # This could be mixed up, but it is either not important, or correct, or misconfigured anyway + setup="${seho[1]:+${seho[0]}}" # Only error if only setup is provided. But we handle it in resolution code which agnostic and treats them as ids + + url=$(adei_resolve_id "setup/adei.txt" "$id" "$host" "$setup") + + if [ -n "$url" ]; then # Get URL, now we can determine host correctly and ignore the ids. + host="$(echo ${url#http*://} | cut -d '/' -f 1)" + unset $setup + else # only 'setup' is not allowed if URL is not configured, so it should be host (or error in configuration) + unset $url # so either we have both (correctly) or only host (correctly) + fi + fi + + local hopo + IFS=':' read -ra hopo <<< "$host" && shift + host="${hopo[0]}" # only non fqdn if also url not set + port=":${hopo[1]:-80}" + [ $port = ":80" ] && port="" + + local fqdn + if [ -z "$url" ]; then + url=$(adei_resolve_id "setup/adei.txt" "$id" "$host" "$setup") + if [ -n "$url" ]; then + fqdn="$(echo ${url#http*://} | cut -d '/' -f 1)" + + IFS=':' read -ra hopo <<< "$fqdn" && shift + host="${hopo[0]}" # again fqdn + port=":${hopo[1]:-80}" + [ $port = ":80" ] && port="" + else + fqdn=$(resolve_fqdn "$host") # this may be not fqdn + [ -n "$fqdn" ] && host="$fqdn" + url="${host}${port}/adei" + fi + fi + + # In some case we miss here "setup", but surely then the password is resolved host-based + adei_auth=$(adei_resolve_id "security/adei.txt" "$id" "$host" "$setup") + [ -n "$adei_auth" ] && adei_auth="$adei_auth@" + + # Now check port + adei_online=$(scripts/ping.pl "$host" "$port") + [ $adei_online -ne 1 ] && return 2 + + # Now build ADEI url + + adei_setup="$setup" + adei_host="$host" + adei_port="$port" + adei_url="${url#http*://}/services" + + + adei_query_version; local err=$? + [ $err -gt 0 ] && return $err + + + if [[ "$server" =~ \&|= ]]; then + adei_source="&$server" + else + adei_source="" + [ -n "$adei_setup" -a "$adei_setup" != "*" ] && adei_source+="&setup=$adei_setup" + [ -n "$server" -a "$server" != "-" ] && adei_source+="&db_server=$server" + + if [ "$database" == "#1" ]; then + databases="$(adei_get_databases)"; err=$? + [ $err -gt 0 ] && { echo "Failed to query ADEI databases: $databases"; return $err; } + [ -z "$databases" ] && { echo "No databases reported by ADEI"; return 6; } + database=$(echo "$databases" | head -n 1) + fi + + [ -n "$database" -a "$database" != "-" ] && adei_source+="&db_name=$database" + fi + + return 0 +} + +function adei_init { + adei_init_ "$@"; local code=$? + + adei_healthy=$(($code == 0)) + adei_process_error "$code" "" "*" "$(adei_print_status "$0" $adei_online $adei_healthy)" +} diff --git a/lib/adei/adei_error.sh b/lib/adei/adei_error.sh new file mode 100644 index 0000000..9de4795 --- /dev/null +++ b/lib/adei/adei_error.sh @@ -0,0 +1,74 @@ +# Error codes: 1 - unknown network, 2 - unreachable, 3 - timeout, 4 - invalid XML/JSON, 5 - parsing error, 6 - set is empty, 7 - service reported error, 8 - parameter error, 9 - unknown, 10-59 - HTTP errors +# http code (xyz) is converted to error code (xz), e.g. 404 -> 44 + +function adei_format_http_error { + err=$1 + echo -n "$(($err / 10))0$(($err % 10))" +} + +# Returns 1 if printing text is recommended +function adei_print_error { + local ret=0 + local code=${1:-0} + local text="$2" + + local service="${3#\*}" + service="${service:-ADEI}" + + local msg + if [ $code -ge 30 -a $code -lt 60 ]; then + msg="HTTP Error: $(adei_format_http_error $code)" + [ $code -eq 41 ] && msg+=" (Authentication Requested)" + [ $code -eq 43 ] && msg+=" (Access Denied)" + elif [ $code -ge 20 -a $code -lt 30 ]; then + msg="HTTP Status: $(adei_format_http_error $code)" + ret=1 + elif [ $code -eq 1 ]; then + msg="Error communicating with $service" + ret=1 + elif [ $code -eq 2 ]; then + msg="ADEI host ($adei_host:$adei_port) unreachable" + elif [ $code -eq 3 ]; then + msg="Timeout waiting for $service" + elif [ $code -eq 4 ]; then + msg="Non-XML response from $service" + ret=1 + elif [ $code -eq 5 ]; then + msg="Error parsing response from $service" + ret=1 + elif [ $code -eq 6 ]; then + msg="Empty response from $service" + ret=1 + elif [ $code -eq 7 ]; then + rep="$(echo "$text" | head -n 1 | sed 's/Error:\?[[:space:]]\+//i')" + if [ ${#rep} -lt 40 ]; then + msg="$service Error: $rep" + else + msg="$service returned a error" + ret=1 + fi + elif [ $code -eq 8 ]; then + msg="Invalid parameter" + else + msg="Unknown Error $code while accessing $service" + fi + + echo -n "$msg" + return $ret +} + +function adei_process_error { + local code=${1:-0}; shift + local text="$1"; shift + local service="$1"; shift + local status="${1:-0}" + + if [ $code -ne 0 ]; then + local msg # local on the same line break error reporting + msg="$(adei_print_error $code "$text" "$service")" + [ $? -eq 1 ] && echo "$text" + echo "$status $msg" + exit + fi +} + diff --git a/lib/adei/adei_print.sh b/lib/adei/adei_print.sh new file mode 100644 index 0000000..aca7735 --- /dev/null +++ b/lib/adei/adei_print.sh @@ -0,0 +1,25 @@ +function adei_print_status { + cmd="$1" + online="$2" + healthy="$3" + + if [[ "$cmd" =~ check_adei_ ]]; then + echo "$healthy" + else + echo "$online $healthy" + fi +} + +function format_time { + offset=$1 + if [ $offset -ge 86400 ]; then + echo "$((offset / 86400))d" + elif [ $offset -ge 3600 ]; then + echo "$((offset / 3600))h" + elif [ $offset -ge 60 ]; then + echo "$((offset / 60))m" + else + echo "${offset}s" + fi +} + diff --git a/lib/adei/adei_version.sh b/lib/adei/adei_version.sh new file mode 100644 index 0000000..b71b1e1 --- /dev/null +++ b/lib/adei/adei_version.sh @@ -0,0 +1,51 @@ +vercomp() { + if [[ $1 == $2 ]] + then + return 0 + fi + local IFS=. + local i ver1=($1) ver2=($2) + # fill empty fields in ver1 with zeros + for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) + do + ver1[i]=0 + done + for ((i=0; i<${#ver1[@]}; i++)) + do + if [[ -z ${ver2[i]} ]] + then + # fill empty fields in ver2 with zeros + ver2[i]=0 + fi + if ((10#${ver1[i]} > 10#${ver2[i]})) + then + return 1 + fi + if ((10#${ver1[i]} < 10#${ver2[i]})) + then + return 2 + fi + done + return 0 +} + +adei_version_check() { + vercomp $adei_revision $1 + res=$? + if [ $res -eq 1 ]; then + return 0 + elif [ $res -eq 2 ]; then + return 1; + fi + + if [ -z "$2" -o -z "$adei_date" ]; then + return 0 + fi + + if [ $adei_date -ge $2 ]; then + return 0 + fi + + return 1 +} + diff --git a/lib/helpers.sh b/lib/helpers.sh new file mode 100644 index 0000000..b562eb6 --- /dev/null +++ b/lib/helpers.sh @@ -0,0 +1,9 @@ +function in_array() { + local hay needle=$1 + shift + for hay; do + [[ $hay == $needle ]] && return 0 + done + + return 1 +} diff --git a/lib/nagios/nagios.sh b/lib/nagios/nagios.sh new file mode 100755 index 0000000..40631c1 --- /dev/null +++ b/lib/nagios/nagios.sh @@ -0,0 +1,125 @@ +cd $(dirname "$0") + +. setup/parameters.sh + +function nagios_find_host { + echo "$@" | grep -oP '\-H\s*\K[^\s]*' +} + +function find_host_param { + local id="$1" && shift + local pname="$1" && shift + local defval="$1" && shift + + local val=$(cat setup/${pname}.txt | grep -P "^$id" | awk '{ print $2 }') + [ -n "$val" ] || val="$defval" + + echo -n "$val" +} + +function nagios_find_host_param { + local pname="$1" && shift + local defval="$1" && shift + local host=$(nagios_find_host "$@") + + find_host_param "$host" "$pname" "$defval" +} + +function resolve_fqdn { + local host="$1" && shift + + if [[ ! $host =~ \. ]]; then + local domain=$(find_host_param "$host" domains "$default_domain") + host+=".$domain" + fi + + echo -n $host +} + +function resolve_ip { + local host="$1" && shift + + if [[ ! "$host" =~ ^[[:digit:]] ]]; then + local fqdn=$(resolve_fqdn "$host") + host=$(dig +short "$fqdn" A | head -n 1 | tr -d '\n') + if [ $? -ne 0 -o -z "$host" ]; then + echo "DNS resolution for host ($fqdn) failed: $(dig +short "$fqdn" A 2>&1)" + exit 2 + fi + fi + + echo -n "$host" +} + +function nagios_run { + if [[ "$1" =~ ^- ]]; then + cmd=${nagios_plugins}/$(basename $0) + else + cmd=$1 && shift + [[ "$cmd" =~ ^/ ]] || cmd="${nagios_plugins}/$cmd" + fi + + ARGS="" + while [[ $# -gt 0 ]]; do + key="$1" && shift + + case "$key" in + -H) + host="$1" && shift + ip=$(resolve_ip "$host") + if [ $? -eq 0 -a -n "$ip" ]; then + ARGS+=" ${key} $ip" + else + echo "$ip" + exit $? + fi + ;; + *) + ARGS+=" $key" + esac + done + + [ -n "$debug" ] && echo "$(date) $cmd" "$ARGS" >> /tmp/nagios.log + eval "$cmd" "$ARGS" +} + +function nagios_parse { + cmd="$1"; shift + + output=$($cmd "$@") + exit_code=$? + + if [ $exit_code -eq 0 ]; then + last_line=$(echo "$output" | tail -1) + + status=$(echo $last_line | cut -d ' ' -f 1) + [[ "$status" =~ ^[0-9]$ ]] || status=0 + echo -n ${last_line#$status} + else + status=0 + fi + + if [ $status -ne 1 ]; then + echo -n " -- " + + lines=$(echo "$output" | sed '/^[[:space:]]*$/d' | wc -l) + if [ $lines -gt 1 ]; then + echo "$output" | sed '/^[[:space:]]*$/d' | head -n 1 | tr -d '\n' + echo " ... " + echo "------------------" + echo "$output" | head -n -1 + else + echo "$output" | sed '/^[[:space:]]*$/d' | head -n -1 + fi + else + echo + fi + + if [ "$status" -eq 0 ]; then + exit "2" + elif [ "$status" -eq 1 ]; then + exit "0" + else + exit "1" + fi +} diff --git a/lib/remote/README.txt b/lib/remote/README.txt new file mode 100644 index 0000000..c5998f8 --- /dev/null +++ b/lib/remote/README.txt @@ -0,0 +1,34 @@ +conky format +============ + - Server status + * ping works + * no output from 'check_server_status.sh' and additional listed checks + [*] Checks for additional listed services 'check_<service>_status.sh'. + - The optional status is in the beginning of first line (0 - red, 1 - green, 2 - yellow). Otherwise, 'red' if any output (also if first word is non-number on the first string). + - If first line starts from the status, the rest of the line is considered a header and reported on the status line. Everything else goes to textual section bellow. + [headers] + + ... Textual information reported by 'check_server_status.sh' and check_*_status.sh scripts. The format + server:port[:service] text.... + + - Extra info for DarkSoft servers + * VPN to the server is working (checked with the ping). This not included in the scripted version, instead server traffic reported directly here. + # # Traffic on VPN interface from/to + + - Server traffic + in/out/forw. Yellow/Red if above specified threshold. No additional errors are reported here. + + - Services (operated by local scripts in 'services' directory) + * Online + * Healthy + [headers] Information about service operation + [errors] Short information on critical errors are reported here (in conky, we push everything in the text section) + + ... Larger textual information about the problems. + + + Service format is following (status is on the last line and mandatory): + * Critical Lines starting with '*' contain critical errors and highlighted (remote) / reported in the service table (conky) + Text This is normal problem description reported in the textual area + # # [header] Two statuses (0 - error, 1 - ok, 2 - warning) and optional header with information about service operation +
\ No newline at end of file diff --git a/lib/remote/print.sh b/lib/remote/print.sh new file mode 100644 index 0000000..a0fdcbe --- /dev/null +++ b/lib/remote/print.sh @@ -0,0 +1,168 @@ +# underlines 4;30,... blinking 5:30,... +# backgrounds: 40,... + +declare -A colors=( + [black]='0;30' + [red]='0;31' + [green]='0;32' + [orange]='0;33' + [blue]='0;34' + [purple]='0;35' + [cyan]='0;36' + [lightgray]='0;37' + [gray]='1;30' + [lightred]='1;31' + [lightgreen]='1;32' + [yellow]='1;33' + [lightblue]='1;34' + [lightpurple]='1;35' + [lightcyan]='1;36' + [white]='1;37' +) + +background="" +foreground="" + + + + +# Fixing color map +#echo -ne "\e[44m" +#echo -ne '\x1B[K' + +function set_background { + if [ -n "$background" ]; then + echo -ne "$background" + echo -ne '\x1B[K' + fi +} + +function set_color { + local color=${1:-""} + local effect=${2:-""} + + c=${colors[$color]} + + + case "$effect" in + 'u') + c=$(echo $c | sed -r "s/^0/4/ ; s/^1/1;4/") + ;; + esac + + [ -n "$color" ] && echo -ne "\033[${c}m" + set_background +} + +function reset_color { + echo -ne "\033[0m" + + set_background + [ -n "$foreground" ] && set_color "$foreground" +} + +function finish { + echo -ne "\033[0m" + echo +} + +function configure_palete { + case $1 in + blue) + background="\e[1;44m" + foreground="white" + ;; + *) + # Lightgray and Yellow are almost invisible on white + colors[yellow]=${colors[orange]} + colors[white]=${colors[black]} + colors[lightgray]=${colors[gray]} + colors[cyan]=${colors[blue]} + ;; + esac + + set_background + reset_color +} + +function decorate { + local output="$1" + local color=${2:-""} + local effect=${3:-""} + + if [ -n "$color" ]; then + set_color $color $effect + echo -ne "${output}" + reset_color + else + echo -ne "$output" + fi +} + +function eol { + sed 's/$/\x1B[K/' +} + +function print_eol { + echo -e '\x1B[K' +} + + + +function print { + local output="$1" + local color=${2:-""} + local char_limit=${3:-$fold} + local line_limit=${4:-0} + + local cmd="decorate \"${output}\" \"$color\" | fold -s -w $char_limit" + [ $line_limit -gt 0 ] && cmd="$cmd | head -n $line_limit" + + eval "$cmd" | eol +} + + +function print_hline { + local color=${1:-"gray"} + local cols=${COLUMNS:-$(tput cols)} + + decorate $(printf '%*s' $cols '' | tr ' ' -) "$color" + echo | eol +} + +function print_table { + # The problem here is that all escapes for colors are treated as normal visible symbols + sed "s/ ::: /@/g" | column -t -s "@" -o " " | eol +} + +function decorate_table { + print_hline + cat - + print_hline +} + +function print_status { + local status="$1" + + if [[ $status =~ ^.$ ]]; then + case $status in + 0) + decorate "*" "red" + ;; + 1) + decorate "*" "green" + ;; + 2) + decorate "*" "yellow" + ;; + *) + decorate "$status" "red" + ;; + esac + else + decorate "?" "red" + fi + echo -n " " +} + +clear diff --git a/lib/remote/report.sh b/lib/remote/report.sh new file mode 100644 index 0000000..e6766a4 --- /dev/null +++ b/lib/remote/report.sh @@ -0,0 +1,51 @@ +function simple_report { + local generator="$1" + local filter="${2:-cat}" + { + eval "$generator 12>/dev/fd/12 | $filter" + report=$(cat<&12) + } 12<<EOF +EOF + wait +} + + +function short_report { + local generator="$1" + local filter="${2:-print_table | decorate_table}" + + configure_palete "$palete" + simple_report "$generator" "$filter" + finish +} + + +function standart_report { + local generator="$1" + local filter="${2:-print_table | decorate_table}" + + configure_palete "$palete" + simple_report "$generator" "$filter" + + print "$report" + echo + finish +} + + +function report { + # Eval breaks output for some reason + case $report in + simple_report) + simple_report "$@" + ;; + short_report) + short_report "$@" + ;; + standart_report) + standart_report "$@" + ;; + default) + echo "Report is not implemented" + esac +} diff --git a/lib/remote/run.sh b/lib/remote/run.sh new file mode 100644 index 0000000..fdd7311 --- /dev/null +++ b/lib/remote/run.sh @@ -0,0 +1,13 @@ +function run_ { + local output=$(eval source "$@") + + flock -x $0 echo -e "$output" +} + +function run { + if [ $parallel -gt 0 ]; then + run_ "$@" & + else + run_ "$@" + fi +} diff --git a/lib/remote/status.sh b/lib/remote/status.sh new file mode 100644 index 0000000..7bef6c8 --- /dev/null +++ b/lib/remote/status.sh @@ -0,0 +1,196 @@ +. setup/remote.sh +. lib/remote/print.sh +. lib/remote/report.sh +. lib/remote/run.sh + +function check_server_traffic { + local result="$1" + local yellow=${2:-0} + local red=${3:-0} + + local name=("in" "out" "fwd") + + local traf + read -ra traf <<< $result + if [ ${#traf[@]} -ne 3 ]; then + [ -z "$result" ] && result="No info received" + print "$result" "red" $fold 1 + return + fi + + local output="" + for i in $(seq 0 2); do + if ! [[ ${traf[$i]} =~ ^[0-9]+$ ]]; then + print "$result" "red" $fold 1 + return + fi + + local val=$(printf "% 4u" $((${traf[$i]} / 1024 / 1024 / 1024))) + if [ $red -gt 0 -a $val -gt $red ]; then + val=$(decorate "$val GB" "red") + elif [ $yellow -gt 0 -a $val -gt $yellow ]; then + val=$(decorate "$val GB" "yellow") + else + val="$val GB" + fi + +# output="$output${output:+, }${name[$i]}: $val" + output="$output${output:+, } $val" + done + +# print "$output" + print "in/out/fwd: $output" +} + +function check_server_ { + local service=$1 && shift + + local hopo + IFS=':' read -ra hopo <<< $1 && shift + local host=${hopo[0]} + local port=${hopo[1]:-22} + + local result=$(ssh $ssh_params -p $port root@$host /opt/scripts/check_server_$service.sh 2>&1 ) + + case "$service" in + 'traffic') + check_server_traffic "$result" "$@" + ;; + *) + print "$result" + esac + +} + + +function check_server_status { + local hopo + IFS=':' read -ra hopo <<< $1 && shift + local host=${hopo[0]} + local port=${hopo[1]:-22} + local services="$@" + + local ping_output=$(scripts/ping.pl $host $port $timeout) + print_status "$ping_output" + + if [ "$services" == "-" ]; then return; fi + + if [ "$ping_output" == "1" ]; then + local output=$(ssh $ssh_params -p $port root@$host /opt/scripts/check_server_status.sh 2>&1) + + local status=1 + [ -n "$output" ] && status=0 && output="\n$(decorate "$host:$port" "cyan" "u")\n$output\n" + print_status $status + + # Check Additional services, error is reported if anything provides information + local headers="" + if [ -n "$services" ]; then + for service in "$services"; do + if [[ "$service" =~ ^vpn/(.*)$ ]]; then + local ip=${BASH_REMATCH[1]} + [ $(hostname) == "styx" ] && check_server_status "$ip" "-" + else + local service_status=1 + local service_output=$(ssh $ssh_params -p $port root@$host /opt/scripts/check_${service}_status.sh 2>&1 | sed 's/^[[:space:]]*//;/^$/d') + if [ -n "$service_output" ]; then + first_line=$(echo "$service_output" | head -n 1) + if [[ "$first_line" =~ ^([0-9]+)[[:space:]](.*)$ ]]; then + service_status=${BASH_REMATCH[1]} + service_output=$(sed "1 d" <<< "$service_output") + if [ -n "${BASH_REMATCH[2]}" ]; then + service_header=$(sed -r "s/\\$\{color\s+([^}]*)\}/\$(set_color \\1)/g" <<< "${BASH_REMATCH[2]}") #" + headers="$headers $service_header" + fi + else + service_status=0 + fi + + if [ -n "$service_output" ]; then + [ -z "$output" ] && output="\n$(decorate "$host:$port" "cyan" "u")" + output="${output}\n $(decorate "$service" "gray" "u")\n$(echo ${service_output} | sed 's/^/ /')" + fi + fi + fi + + done + fi + + print " ::: ${headers}" + #report="$report<section>$output" + if [ -n "$output" ]; then + flock -x $0 echo "${output}" >&12 + fi + else + print_status "x" + for service in "$services"; do + print_status "x" + done + fi +} + +function check_service { + local service="$1" && shift + local id="$1" && shift + local args="$@" + + local output=$(service/check_${service}.sh ${id} "$@" 2>&1 | sed 's/^[[:space:]]*//;/^$/d') + + local info=$(echo "$output" | tail -n 1) + + local online=0 + local health=0 + local header="" + if [[ "$info" =~ ^([0-9]+)[[:space:]]+([0-9]+)[[:space:]]+(.*)$ ]]; then + online=${BASH_REMATCH[1]} + health=${BASH_REMATCH[2]} + header=${BASH_REMATCH[3]} + + output=$(sed '$ d' <<< "$output") + fi + + print_status "$online" + print_status "$health" + + header=$(sed -r "s/\\$\{color\s+([^}]*)\}/\$(set_color \\1)/g" <<< "$header") # " + print " ::: ${header}" + + + important=$(grep "^\*" <<< "$output") + messages=$(grep -v "^\*" <<< "$output") + + if [ -n "$output" ]; then + output="\n$(decorate "$service:$id" "cyan" "u")\n$important\n$(set_color gray)$messages$(reset_color)\n" + flock -x $0 echo "${output}" >&12 + fi +} + + +function check__ { + local args + local title="$1" && shift + read -ra args <<< "$1" && shift + local host=${args[0]}; + + print "$(decorate $title "purple") ::: " | sed -r "s/\\$\{color\s+([^}]*)\}/\$(set_color \\1)/g; " + + local service + for service in "$@"; do + service=$(sed -r "s/<([0-9]+)>/\${args[\\1]}/g; s/<([^>]+)>/\${\\1}/g" <<< "$service") # " + ( eval "$service" ) + done + print_eol +} + +function check_ { + # Buffer the output + local output=$(check__ "$@") + echo -e "$output" +} + +function check { + if [ $parallel -gt 0 ]; then + check_ "$@" & + else + check_ "$@" + fi +} |