Commit
All checks were successful
Ansible Lint |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |2696|18|2678|10|:-1: Reference build: <a href="https://jenkins.evolix.org/job/gitea/job/ansible-roles/job/monitoringctl/8//ansiblelint">Evolix » ansible-roles » monitoringctl #8</a>
gitea/ansible-roles/pipeline/head This commit looks good

This commit is contained in:
William Hirigoyen 2024-03-08 18:17:38 +01:00
parent 6aab5f1aa2
commit 3f3e446949
7 changed files with 826 additions and 713 deletions

View file

@ -5,21 +5,27 @@
#
readonly PROGNAME=$(basename $0)
readonly base_dir="/var/lib/monitoringctl"
readonly log_file="/var/log/monitoringctl.log"
readonly VERSION="24.04.00"
# Default disable duration
duration="1h"
# Load common functions and vars
readonly lib_dir="/usr/local/lib/monitoringctl"
if [ -r "${lib_dir}/common" ]; then
# shellcheck source=monitoringctl_common
source "${lib_dir}/common"
else
>&2 echo "Error: missing ${lib_dir}/common file."
exit 1
fi
usage() {
function show_help() {
cat <<END
$PROGNAME disables or enables NRPE alerts wrapped by the script 'alerts_wrapper' in NRPE configuration.
Usage: $PROGNAME disable [-d|--during <DURATION>] <CHECK_NAME|ALL>
$PROGNAME enable <CHECK_NAME|ALL>
Usage: $PROGNAME disable [-d|--during <DURATION>] <WRAPPER_NAME|all>
$PROGNAME enable <WRAPPER_NAME|all>
$PROGNAME help
CHECK_NAME: the name given to '--name' option of 'alerts_wrapper'.
WRAPPER_NAME: The name given to '--name' option of 'alerts_wrapper'.
DURATION: Duration of alert disabling.
Can be '1d' for 1 day, '5m' for 5 minutes or more complex
expressions like '1w2d10m42s' (if no time unit is provided,
@ -28,115 +34,78 @@ DURATION: Duration of alert disabling.
END
}
error() {
# $1: error message
>&2 echo "$1"
usage
exit 1
}
time_to_seconds() {
# $1: time in string format
if echo "${1}" | grep -E -q '^([0-9]+[wdhms])+$'; then
echo "${1}" | sed 's/w/ * 604800 + /g; s/d/ * 86400 + /g; s/h/ * 3600 + /g; s/m/ * 60 + /g; s/s/ + /g; s/+ $//' | xargs expr
elif echo "${1}" | grep -E -q '^([0-9]+h[0-9]+$)'; then
echo "${1}" | sed 's/h/ * 3600 + /g; s/$/ * 60/' | xargs expr
elif echo "${1}" | grep -E -q '^([0-9]+m[0-9]+$)'; then
echo "${1}" | sed 's/m/ * 60 + /g' | xargs expr
else
error "Invalid duration: '${1}'."
fi
}
get_disable_names() {
grep "alerts_wrapper" -Rs /etc/nagios/ | grep -vE "^\s*#" | awk '{ for (i=1; i<=NF; i++) { if ($i ~ /^(-n|--name)$/) { print $(i+1); break } } }' | tr ',' '\n' | sort | uniq
}
disable_alerts () {
# $1: check name, $2: duration_sec
function disable_alerts() {
# $1: wrapper name, $2: duration_sec
now_secs=$(date +"%s")
disable_until_secs=$(( now_secs + $2 ))
disable_file_path="${base_dir}/${1}_alerts_disabled"
disable_until_secs=$(( now_secs + ${2} ))
disable_file_path="$(get_disable_file_path "${1}")"
echo "${disable_until_secs}" > "${disable_file_path}"
chmod 0644 "${disable_file_path}"
log_disable "$1"
log "${1} alerts disabled by $(logname || echo unknown)"
}
enable_alerts () {
# $1: check name
disable_file_path="${base_dir}/${1}_alerts_disabled"
function enable_alerts() {
# $1: wrapper name
disable_file_path="$(get_disable_file_path "${1}")"
if [ -e "${disable_file_path}" ]; then
rm "${disable_file_path}"
fi
log_enable "$1"
log "${1} alerts enabled by $(logname || echo unknown)"
}
now () {
date --iso-8601=seconds
}
log_disable () {
# $1: check name
echo "$(now) - alerts_switch: $1 alerts disabled by $(logname || echo unknown)" >> $log_file
}
log_enable () {
# $1: check name
echo "$(now) - alerts_switch: $1 alerts enabled by $(logname || echo unknown)" >> $log_file
}
main () {
install --mode=0755 --directory "${base_dir}"
function main() {
install --mode=0755 --directory "${var_dir}"
if [ "${action}" == 'enable' ]; then
if [ "${check_name}" == "all" ]; then
for check in $(get_disable_names); do
enable_alerts "${check}"
if [ "${wrapper_name}" == "all" ]; then
for wrapper in $(get_wrappers_names); do
enable_alerts "${wrapper}"
done
else
enable_alerts "${check_name}"
enable_alerts "${wrapper_name}"
fi
elif [ "${action}" == 'disable' ]; then
duration_sec=$(time_to_seconds "${duration}")
if [ "${check_name}" == "all" ]; then
for check in $(get_disable_names); do
disable_alerts "${check}" "${duration_sec}"
if [ "${wrapper_name}" == "all" ]; then
for wrapper in $(get_wrappers_names); do
disable_alerts "${wrapper}" "${duration_sec}"
done
else
disable_alerts "${check_name}" "${duration_sec}"
disable_alerts "${wrapper_name}" "${duration_sec}"
fi
elif [ "${action}" == 'help' ]; then
usage
show_help
fi
}
while :; do
case "$1" in
case "${1}" in
enable|disable|help)
action="$1"
action="${1}"
shift;;
-d|--during)
if [ "$#" -gt 1 ]; then
duration="$2"
if filter_duration "${2}"; then
duration="${2}"
else
usage_error "Option --during: \"${2}\" is not a valid duration."
fi
else
error "Missing --during argument."
fi
shift; shift;;
*)
if [ -n "$1" ]; then
get_disable_names | grep --quiet -E "^$1$"
arg_is_in_disable_names_rc=$?
if [ "${arg_is_in_disable_names_rc}" -eq 0 ] || [ "$1" == "all" ]; then
check_name="$1"
if [ -n "${1}" ]; then
if is_wrapper "${1}" || [ "${1}" == "all" ]; then
wrapper_name="${1}"
else
error "Unknown argument '$1', or NAME not defined in NRPE configuration."
error "Unknown argument '${1}', or NAME not defined in NRPE configuration."
fi
else
if [ -z "${action}" ]; then
error "Missing action argument."
elif [ -z "$1" ]; then
elif [ -z "${1}" ]; then
break
fi
fi
@ -145,13 +114,15 @@ while :; do
esac
done
if [ -z "${check_name}" ] && [ "${action}" != 'help' ] ; then
error "Missing CHECK_NAME argument."
if [ -z "${wrapper_name}" ] && [ "${action}" != 'help' ] ; then
error "Missing WRAPPER_NAME."
fi
readonly check_name
readonly duration
readonly action
if [ -z "${duration}" ]; then
duration="${default_disabled_time}"
fi
readonly wrapper_name duration action
main

View file

@ -4,123 +4,56 @@
# https://gitea.evolix.org/evolix/ansible-roles/src/branch/stable/nagios-nrpe
#
readonly VERSION="21.04"
readonly PROGNAME=$(basename $0)
readonly VERSION="24.04.00"
# Location of disable files
readonly base_dir="/var/lib/monitoringctl"
# Load common functions and vars
readonly lib_dir="/usr/local/lib/monitoringctl"
if [ -r "${lib_dir}/common" ]; then
# shellcheck source=monitoringctl_common
source "${lib_dir}/common"
else
>&2 echo "Error: missing ${lib_dir}/common file."
exit 1
fi
# If no datetime is found in file, this value is used
readonly default_disabled_time="1d"
show_version() {
cat <<END
alerts_wrapper version ${VERSION}
Copyright 2018-2021 Evolix <info@evolix.fr>,
Jérémy Lecour <jlecour@evolix.fr>
and others.
alerts_wrapper comes with ABSOLUTELY NO WARRANTY.This is free software,
and you are welcome to redistribute it under certain conditions.
See the GNU General Public License v3.0 for details.
END
}
show_help() {
function show_help() {
cat <<END
alerts_wrapper wraps an NRPE command and overrides the return code.
Usage: alerts_wrapper --name <CHECK_NAME> <CHECK_COMMAND>
Usage: alerts_wrapper <CHECK_NAME> <CHECK_COMMAND> (deprecated)
Usage: alerts_wrapper --name <WRAPPER_NAME> <CHECK_COMMAND>
Usage: alerts_wrapper <WRAPPER_NAME> <CHECK_COMMAND> (deprecated)
Options
--name Check name (like load, disk1…)
--name Wrapper name, it is very recommended to use the check name (like load, disk1…).
Special name: 'all' is already hard-coded.
-h, --help Print this message and exit.
-V, --version Print version and exit.
END
}
time_to_seconds() {
# $1: formated time string
if echo "${1}" | grep -E -q '^([0-9]+[wdhms])+$'; then
echo "${1}" | sed 's/w/ * 604800 + /g; s/d/ * 86400 + /g; s/h/ * 3600 + /g; s/m/ * 60 + /g; s/s/ + /g; s/+ $//' | xargs expr
elif echo "${1}" | grep -E -q '^([0-9]+$)'; then
echo "${1} * 3600" | xargs expr
else
return 1
fi
}
delay_from_disable_file() {
# $1: disabled file containing the re-enable time in sec
enable_secs=$(grep -v -E "^\s*#" "${1}" | grep -E "^[0-9]+$" | head -n1 | awk '{print $1}')
# If file is empty, use file last change date plus default disabled time
if [ -z "${enable_secs}" ]; then
file_last_change_secs=$(stat -c %Z "$1")
default_disabled_time_secs="$(time_to_seconds "${default_disabled_time}")"
enable_secs="$(( file_last_change_secs + default_disabled_time_secs))"
fi
now_secs=$(date +"%s")
echo $(( enable_secs - now_secs ))
}
delay_to_string() {
#$1 delay in secs
delay_days="$(( delay /86400 ))"
if [ "${delay_days}" -eq 0 ]; then delay_days=""
else delay_days="${delay_days}d"; fi
delay_hours="$(( (delay %86400) /3600 ))"
if [ "${delay_hours}" -eq 0 ]; then delay_hours=""
else delay_hours="${delay_hours}h"; fi
delay_minutes="$(( ((delay %86400) %3600) /60 ))"
if [ "${delay_minutes}" -eq 0 ]; then delay_minutes=""
else delay_minutes="${delay_minutes}m"; fi
delay_seconds="$(( ((delay %86400) %3600) %60 ))"
if [ "${delay_seconds}" -eq 0 ]; then delay_seconds=""
else delay_seconds="${delay_seconds}s"; fi
echo "${delay_days}${delay_hours}${delay_minutes}${delay_seconds}"
}
is_disabled() {
# $1: disabled file containing the re-enable time in sec
if [ -e "$1" ]; then
delay=$(delay_from_disable_file "$1")
if [ "${delay}" -le "0" ]; then
echo "False"
enable_check "${check_name}"
else
echo "True"
fi
else
echo False
fi
}
enable_check() {
# $1: check name
function enable_wrapper() {
# $1: wrapper name
if [ "$(id -u)" -eq "0" ] ; then
/usr/local/bin/alerts_switch enable "$1"
/usr/local/bin/alerts_switch enable "${1}"
else
sudo /usr/local/bin/alerts_switch enable "$1"
sudo /usr/local/bin/alerts_switch enable "${1}"
fi
}
main() {
is_disabled=$(is_disabled "${disable_file}")
function main() {
is_disabled="$(is_disabled "${wrapper_name}")"
if [ -e "${disable_file}" ] && [ "${is_disabled}" == "False" ]; then
enable_wrapper "${wrapper_name}"
fi
timeout_command=""
if [ "${is_disabled}" == "True" ]; then
timeout_command="timeout 9"
fi
check_stdout=$(${timeout_command} ${check_command})
check_stdout="$(${timeout_command} ${check_command})"
check_rc=$?
if [ "${is_disabled}" == "True" ] && [ "${check_rc}" -eq 124 ] && [ -z "${check_stdout}" ]; then
@ -128,9 +61,11 @@ main() {
fi
if [ "${is_disabled}" == "True" ]; then
delay=$(delay_from_disable_file "${disable_file}")
delay_str="$(delay_to_string "${delay}")"
echo "ALERT DISABLED until ${delay_str} - ${check_stdout}"
enable_time="$(get_enable_time "${wrapper_name}")"
enable_delay="$(enable_delay "${enable_time}")"
delay_str="$(delay_to_string "${enable_delay}")"
enable_date="$(date --date "+${enable_delay} seconds" "+%d %h %Y at %H:%M:%S")"
echo "ALERT DISABLED until ${enable_date} (${delay_str} left) - ${check_stdout}"
else
echo "${check_stdout}"
fi
@ -151,7 +86,7 @@ if [[ "${1}" =~ -.* ]]; then
# parse options
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
while :; do
case $1 in
case "${1}" in
-h|-\?|--help)
show_help
exit 0
@ -162,22 +97,22 @@ if [[ "${1}" =~ -.* ]]; then
;;
-n|--name)
# with value separated by space
if [ -n "$2" ]; then
check_name=$2
if [ -n "${2}" ]; then
wrapper_name="${2}"
shift
else
printf 'ERROR: "--name" requires a non-empty option argument.\n' >&2
exit 1
exit 2
fi
;;
-n|--name=?*)
# with value separated by =
check_name=${1#*=}
wrapper_name="${1#*=}"
;;
-n|--name=)
# without value
printf 'ERROR: "--name" requires a non-empty option argument.\n' >&2
exit 1
exit 2
;;
--)
# End of all options.
@ -186,8 +121,8 @@ if [[ "${1}" =~ -.* ]]; then
;;
-?*)
# ignore unknown options
printf 'WARN: Unknown option : %s\n' "$1" >&2
exit 1
printf 'ERROR: Unknown option : %s\n' "${1}" >&2
exit 2
;;
*)
# Default case: If no more options then break out of the loop.
@ -201,27 +136,26 @@ if [[ "${1}" =~ -.* ]]; then
check_command="$*"
else
# no option is passed (backward compatibility with previous version)
# treat the first argument as check_name and the rest as the command
check_name="${1}"
# treat the first argument as wrapper_name and the rest as the command
wrapper_name="${1}"
shift
check_command="$*"
fi
if [ -z "${check_name}" ]; then
printf 'ERROR: You must specify a check name, with --names.\n' >&2
if [ -z "${wrapper_name}" ]; then
printf 'ERROR: You must specify a wrapper name, with --names.\n' >&2
exit 2
fi
if [ -z "${check_command}" ]; then
printf 'ERROR: You must specify a command to execute.\n' >&2
exit 2
fi
if [ -e "${base_dir}" ] && [ ! -x "${base_dir}" ]; then
printf "ERROR: %s exists but is no reachable.\n" "${base_dir}"
if [ -e "${var_dir}" ] && [ ! -x "${var_dir}" ]; then
printf "ERROR: %s exists but is no reachable.\n" "${var_dir}"
exit 2
fi
readonly check_name
readonly check_command
readonly disable_file="${base_dir}/${check_name}_alerts_disabled"
disable_file="$(get_disable_file_path "${wrapper_name}")"
readonly wrapper_name check_command disable_file
main

393
nagios-nrpe/files/monitoringctl Executable file
View file

@ -0,0 +1,393 @@
#!/usr/bin/env bash
#set -x
readonly PROGNAME=$(basename $0)
readonly VERSION="24.04.00"
# Load common functions and vars
readonly lib_dir="/usr/local/lib/monitoringctl"
if [ -r "${lib_dir}/common" ]; then
# shellcheck source=monitoringctl_common
source "${lib_dir}/common"
else
>&2 echo "Error: missing ${lib_dir}/common file."
exit 1
fi
function show_help() {
cat <<EOF
monitoringctl version ${VERSION}.
monitoringctl gives some control over NRPE checks and alerts.
Usage: monitoringctl [OPTIONS] ACTION ARGUMENTS
GENERAL OPTIONS:
-h, --help Print this message and exit.
-V, --version Print version number and exit.
ACTIONS:
status [CHECK_NAME|all]
Print whether alerts are enabled or not (silenced).
If alerts are disabled (silenced), show comment and time left before automatic re-enabling.
check [--bypass-nrpe] CHECK_NAME
Ask CHECK_NAME status to NRPE as an HTTP request.
Indicates which command NRPE has supposedly run (from its configuration).
-b, --bypass-nrpe Execute directly command from NRPE configuration,
as user nagios, without passing the request to NRPE.
disable CHECK_NAME|all [--during DURATION] --comment 'COMMENT'
Disable (silence) CHECK_NAME or all alerts for DURATION and write COMMENT into the log.
Checks output is still printed, so alerts history won't be lost.
enable CHECK_NAME|all --comment 'COMMENT'
Re-enable CHECK_NAME or all alerts
show CHECK_NAME
Show NPRE command(s) configured for CHECK_NAME
COMMENT:
Comment string to be written in log (mandatory).
DURATION:
Time (string) during which alerts will be disabled (optional, default: "1h").
Format:
You can use 'd' (day), 'h' (hour) and 'm' (minute) , or a combination of them, to specify a duration.
Examples: '2d', '1h', '10m', '1h10' ('m' is guessed).
NOTES
For actions disable, enable and status, CHECK_NAME is actually the --name option passed to alerts_wrapper, and not the NRPE check name. Both check name and alerts_wrapper --name option should be equal in NRPE configuration to avoid confusion.
Log path: ${log_file}
EOF
}
function check() {
# $1: check name
readonly check_nrpe_bin="/usr/lib/nagios/plugins/check_nrpe"
if [ ! -f "${check_nrpe_bin}" ]; then
>&2 echo "${check_nrpe_bin} is missing, please install nagios-nrpe-plugin package."
exit 1
fi
conf_lines="$(get_nrpe_conf "${nrpe_conf_path}")"
server_address=$(echo "$conf_lines" | grep "server_address" | tail -n1 | cut -d'=' -f2)
if [ -z "${server_address}" ]; then server_address="127.0.0.1"; fi
server_port=$(echo "$conf_lines" | grep "server_port" | tail -n1 | cut -d'=' -f2)
if [ -z "${server_port}" ]; then server_port="5666"; fi
check_commands=$(get_check_commands "$1")
if [ -n "${check_commands}" ]; then
check_command=$(echo "${check_commands}" | tail -n1)
else
error "Warning: no command found in NRPE configuration for check '${1}'. Aborted."
fi
if [ "${bypass_nrpe}" = "False" ]; then
request_command="${check_nrpe_bin} -H ${server_address} -p ${server_port} -c check_$1 2&>1"
else
request_command="sudo -u nagios -- ${check_command}"
fi
check_output=$(${request_command})
rc=$?
if [ "${bypass_nrpe}" = "False" ]; then
echo "NRPE service output (on ${server_address}:${server_port}):"
else
echo "Direct check output (bypassing NRPE):"
fi
echo "${check_output}"
exit "${rc}"
}
function disable_alerts() {
# $1: check name, $2: comment
if ! command -v alerts_switch &> /dev/null; then
error "Error: script 'alerts_switch' is not installed. Aborted."
fi
if [ "${1}" = "all" ]; then
checks="$(get_checks_names)"
else
checks="${1}"
fi
# Verify that checks to disable are wrapped
unwrappeds="$(not_wrapped_checks)"
unwrapped_checks="$(comm -12 <(echo "${checks}") <(echo "${unwrappeds}"))"
if [ -n "${unwrapped_checks}" ]; then
>&2 printf "Warning: some checks have no alerts_wrapper, they will not be disabled:"
for unwrapped in ${unwrapped_checks}; do
>&2 printf " %s" "${unwrapped}"
done
>&2 printf "\n"
fi
default_msg=""
if [ "${default_duration}" = "True" ]; then
default_msg=" (use --during to change default time)"
fi
if [ "${1}" = "all" ]; then
check_txt="All checks"
else
check_txt="Check ${1}"
fi
cat <<EOF
${check_txt} will be disabled for ${duration}${default_msg}.
Alerts history is kept in our monitoring system.
To re-enable alert(s) before ${duration}, execute as root or with sudo: 'monitoringctl enable ${1} --comment "YOUR REASON"'
EOF
echo -n "Confirm (y/N)? "
read -r answer
if [ "${answer}" != "Y" ] && [ "${answer}" != "y" ]; then
echo "Canceled." && exit 0
fi
log "Action disable ${1} requested for ${duration} by user $(logname || echo unknown)."
log "Comment: '${2}'"
# Log a warning if a check has no wrapper
if [ -n "${unwrapped_checks}" ]; then
log "Warning: some checks have no alerts_wrapper, they will not be disabled:"
for unwrapped in ${unwrapped_checks}; do
log " ${unwrapped}"
done
fi
log "Executing 'alerts_switch disable ${1} --during \"${duration}\"'"
alerts_switch disable "${1}" --during "${duration}"
echo "${1} alerts are now disabled for ${duration}"
}
function enable_alerts() {
# $1: wrapper name, $2: comment
if [ "${1}" != "all" ]; then
is_disabled="$(is_disabled "${1}")"
if [ "${is_disabled}" = "False" ]; then
echo "${1} is already enabled, see 'monitoringctl status'"
exit 0
fi
fi
log "Action enable ${1} requested by user $(logname || echo unknown)."
log "Comment: '${2}'"
log "Executing 'alerts_switch enable ${1}'"
alerts_switch enable "${1}"
echo "${1} alerts are now enabled."
}
# Show NRPE command(s) configured for a check
function show_check_commands() {
# $1: check name
check_commands=$(get_check_commands "${1}")
if [ -z "${check_commands}" ]; then
usage_error "Error: no command found in NRPE configuration for check '${1}."
fi
echo "Available commands (in config order, the last one overwrites the others):"
echo " $check_commands"
check_command=$(echo "${check_commands}" | tail -n1)
echo "Command used by NRPE:"
echo " ${check_command}"
}
# Echo which alerts are enabled or disabled and time left
function alerts_status() {
# $1: check name, "all" or empty
if [ -z "${1}" ] || [ "${1}" = "all" ]; then
checks="$(get_checks_names)"
else
checks="${1}"
fi
printf -- "Check \tStatus \tRe-enable time\n"
printf -- "--------------------\t-----------\t---------------------------------------\n"
for check in $checks; do
enable_str=""
status_str="Enabled"
if ! is_wrapped "${check}"; then
status_str="Not wrapped"
else
is_disabled="$(is_disabled "${check}")"
if [ "${is_disabled}" = "True" ]; then
status_str="Disabled"
enable_time="$(get_enable_time "${check}")"
enable_delay="$(enable_delay "${enable_time}")"
delay_str="$(delay_to_string "${enable_delay}")"
enable_date="$(date --date "+${enable_delay} seconds" "+%d %h %Y at %H:%M:%S")"
enable_str="${enable_date} (${delay_str} left)"
fi
fi
printf -- "%-20s\t%-11s\t%s\n" "${check}" "${status_str}" "${enable_str}"
done
}
### MAIN #########################################
# No root
if [ "$(id -u)" -ne 0 ]; then
>&2 echo "You need to be root (or use sudo) to run ${0}!"
exit 1
fi
# No argument
if [ "$#" = "0" ]; then
show_help
exit 1
fi
# Default arguments and options
action=""
comment=""
duration="${default_disabled_time}"
bypass_nrpe="False"
default_duration="True"
# Parse arguments and options
while :; do
case "${1}" in
-h|-\?|--help)
show_help
exit 0;;
-V|--version)
show_version
exit 0;;
-b|--bypass-nrpe)
bypass_nrpe="True"
shift;;
-d|--during)
if [ "${default_duration}" = "False" ]; then
usage_error "Option --during: defined multiple times."
fi
if [ "$#" -lt 2 ]; then
usage_error "Option --during: missing value."
fi
if filter_duration "${2}"; then
duration="${2}"
else
usage_error "Option --during: \"${2}\" is not a valid duration."
fi
default_duration="False"
shift; shift;;
-c|--comment)
if [ "$#" -lt 2 ]; then
usage_error "Option --comment: missing comment string."
fi
comment="${2}"
shift; shift;;
status|check|enable|disable|show)
action="${1}"
shift;;
*)
if [ -z "${1}" ]; then
break
fi
case "${action}" in
status)
if is_check "${1}" || [ "${1}" = "all" ]; then
check_name="${1}"
else
usage_error "Action ${action}: unknown check '${1}'."
fi
;;
check|show)
if is_check "${1}"; then
check_name="${1}"
else
usage_error "Action ${action}: unknown check '${1}'."
fi
;;
enable|disable)
if is_wrapper "${1}" || [ "${1}" = "all" ]; then
check_name="${1}"
else
if is_check "${1}"; then
error "Error: check '${1}' has no alerts_wrapper, it cannot be disabled. Aborted."
else
# We use the word "check" for the end user,
# but this is actually "unknown wrapper"
usage_error "Action ${action}: unknown check '${1}'."
fi
fi
;;
*)
usage_error "Missing or invalid ACTION argument."
;;
esac
shift;;
esac
done
if [ "$#" -gt 0 ]; then
usage_error "Too many arguments."
fi
case "${action}" in
check|disable|enable|show)
if [ -z "${check_name}" ]; then
usage_error "Action ${action}: missing CHECK_NAME argument."
fi
;;
esac
if [ "${action}" = "enable" ] || [ "${action}" = "disable" ]; then
if [ -z "${comment}" ]; then
usage_error "Action ${action}: missing --comment argument."
fi
fi
if [ ! "${action}" = "disable" ]; then
if [ "${default_duration}" = "False" ]; then
usage_error "Action ${action}: there is no --during option."
fi
fi
case "${action}" in
status)
alerts_status "${check_name}"
;;
check)
check "${check_name}"
;;
show)
show_check_commands "${check_name}"
;;
enable)
enable_alerts "${check_name}" "${comment}"
;;
disable)
disable_alerts "${check_name}" "${comment}"
;;
esac

View file

@ -1,497 +0,0 @@
#!/usr/bin/env bash
#set -x
VERSION="24.03.00"
readonly base_dir="/var/lib/monitoringctl"
readonly log_path="/var/log/monitoringctl.log"
readonly conf_path="/etc/nagios/nrpe.cfg"
function show_help {
cat <<EOF
monitoringctl version ${VERSION}.
monitoringctl gives some control over NRPE checks and alerts.
Usage: monitoringctl [OPTIONS] ACTION ARGUMENTS
GENERAL OPTIONS:
-h, --help Print this message and exit.
-V, --version Print version number and exit.
ACTIONS:
check [--bypass-nrpe] CHECK_NAME
Ask CHECK_NAME status to NRPE as an HTTP request.
Indicates which command NRPE has supposedly run (from its configuration).
-b, --bypass-nrpe Execute directly command from NRPE configuration,
without passing the request to NRPE.
status
Print whether alerts are enabled or not (silenced).
If alerts are disabled (silenced), show comment and time left before automatic re-enabling.
disable CHECK_NAME|all [--during DURATION] --comment 'COMMENT'
Disable (silence) CHECK_NAME or all alerts for DURATION and write COMMENT into the log.
Checks output is still printed, so alerts history won't be lost.
enable CHECK_NAME|all --comment 'COMMENT'
Re-enable all alerts (only global for now)
COMMENT:
Comment string to be written in log (mandatory).
DURATION:
Time (string) during which alerts will be disabled (optional, default: "1h").
Format:
You can use 'd' (day), 'h' (hour) and 'm' (minute) , or a combination of them, to specify a duration.
Examples: '2d', '1h', '10m', '1h10' ('m' is guessed).
Log path: ${log_path}
EOF
}
function show_version {
echo "monitoringctl version ${VERSION}."
}
function usage_error {
>&2 echo "$1"
>&2 echo "Execute \"monitoringctl --help\" for information on usage."
exit 1
}
function now {
date --iso-8601=seconds
}
function log {
# $1: message
echo "$(now) - monitoringctl: $1" >> "${log_path}"
}
### FUNCTIONS FOR CONFIGURATION READING ##########################
# Print NRPE configuration, with includes, without comments
# and in the same order than NRPE does (taking account that
# order changes from Deb10)
function get_conf_from_file {
# $1: NRPE conf file (.cfg)
if [ ! -f "$1" ]; then return; fi
conf_lines=$(grep -E -R -v --no-filename "^\s*#" "$1")
while read -r line; do
if [[ "${line}" =~ .*'include='.* ]]; then
conf_file=$(echo "${line}" | cut -d= -f2)
get_conf_from_file "${conf_file}"
elif [[ "${line}" =~ .*'include_dir='.* ]]; then
conf_dir=$(echo "${line}" | cut -d= -f2)
get_conf_from_dir "${conf_dir}"
else
echo "${line}"
fi
done <<< "${conf_lines}"
}
# Print NRPE configuration, with includes, without comments
# and in the same order than NRPE does (taking account that
# order changes from Deb10)
function get_conf_from_dir {
# $1: NRPE conf dir
if [ ! -d "$1" ]; then return; fi
if [ "${debian_major_version}" -ge 10 ]; then
# From Deb10, NRPE use scandir() with alphasort() function
sort_command="sort"
else
# Before Deb10, NRPE use loaddir(), like find utility
sort_command="cat -"
fi
# Add conf files in dir to be processed recursively
for file in $(find "$1" -maxdepth 1 -name "*.cfg" | ${sort_command}); do
if [ -f "${file}" ]; then
get_conf_from_file "${file}"
elif [ -d "${file}" ]; then
get_conf_from_dir "${file}"
fi
done
}
# Print the checks that are configured in NRPE
function get_checks_list {
echo "${conf_lines}" | grep -E "command\[check_.*\]=" | awk -F"[\\\[\\\]=]" '{sub("check_", "", $2); print $2}' | sort | uniq
}
# Print the commands defined for check $1 in NRPE configuration
function get_check_commands {
# $1: check name
echo "$conf_lines" | grep -E "command\[check_$1\]" | cut -d'=' -f2-
}
# Print the names that are defined in the wrappers of the checks
function get_wrappers_names() {
grep "alerts_wrapper" -Rs /etc/nagios/ | grep -v -E "^\s*#" | awk '{ for (i=1 ; i<=NF; i++) { if ($i ~ /^(-n|--name)$/) { print $(i+1); break } } }' | tr ',' '\n' | sort | uniq
}
### CHECK ACTION ##########################
function check {
# $1: check name
check_nrpe_bin=/usr/lib/nagios/plugins/check_nrpe
if [ ! -f "${check_nrpe_bin}" ]; then
>&2 echo "${check_nrpe_bin} is missing, please install nagios-nrpe-plugin package."
exit 1
fi
server_address=$(echo "$conf_lines" | grep "server_address" | tail -n1 | cut -d'=' -f2)
if [ -z "${server_address}" ]; then server_address="127.0.0.1"; fi
server_port=$(echo "$conf_lines" | grep "server_port" | tail -n1 | cut -d'=' -f2)
if [ -z "${server_port}" ]; then server_port="5666"; fi
check_commands=$(get_check_commands "$1")
if [ -n "${check_commands}" ]; then
if [ "${verbose}" == "True" ]; then
echo "Available commands (in config order, the last one overwrites the others):"
echo "$check_commands"
fi
check_command=$(echo "${check_commands}" | tail -n1)
echo "Command used by NRPE:"
echo " ${check_command}"
else
>&2 echo "Warning: no command found in NRPE configuration for check '${1}'."
if [ "${bypass_nrpe}" = "True" ]; then
>&2 echo "Aborted."
exit 1
fi
fi
if [ "${bypass_nrpe}" = "False" ]; then
request_command="${check_nrpe_bin} -H ${server_address} -p ${server_port} -c check_$1 2&>1"
else
request_command="sudo -u nagios -- ${check_command}"
fi
if [ "${verbose}" == "True" ]; then
echo "Executing:"
echo " ${request_command}"
fi
check_output=$(${request_command})
rc=$?
if [ "${bypass_nrpe}" = "False" ]; then
echo "NRPE service output (on ${server_address}:${server_port}):"
else
echo "Direct check output (bypassing NRPE):"
fi
echo "${check_output}"
exit "${rc}"
}
### (EN|DIS)ABLE-ALERTS ACTIONS ##########################
function filter_duration {
# Format (in brief): XdYhZm
# Minutes unit 'm' is not mandatory after Xh
time_regex="^([0-9]+d)?(([0-9]+h(([0-9]+m?)|([0-9]+m([0-9]+s?)?))?)|(([0-9]+m([0-9]+s?)?)?))?$"
if [[ "$1" =~ ${time_regex} ]]; then
echo "$1"
else
usage_error "Option --during: \"$1\" is not a valid duration."
fi
}
# Check that NRPE commands are wrapped by alerts_wrapper script
function is_nrpe_wrapped {
for check in $(get_checks_list); do
cmd=$(get_check_commands "${check}" | tail -n1)
echo "${cmd}" | grep --quiet --no-messages alerts_wrapper
rc=$?
if [ "${rc}" -ne 0 ]; then
>&2 echo "Warning: check '${check}' has no alerts_wrapper, it will not be disabled:"
>&2 echo " ${cmd}"
fi
done
}
function disable_alerts {
# $1: check name, $2: comment
if ! command -v alerts_switch &> /dev/null; then
>&2 echo "Error: script 'alerts_switch' is not installed."
>&2 echo "Aborted."
exit 1
fi
#TODO Are alerts already disabled ?
# -> mauvais indicateur, cf. le timeout à l'intérieur + le max autorisé dans la commande alerts_wrapper
#if [ -f "${base_dir}/all_alerts_disabled" ]; then
# echo "All alerts are already disabled."
# status
#fi
default_msg="."
if [ "${default_duration}" = "True" ]; then
default_msg=" (default value).
Hint: use --during DURATION to change default time length."
fi
cat <<EOF
Alerts will be disabled for ${duration}${default_msg}
Our monitoring system will continue to gather checks outputs, so alerts history won't be lost.
To re-enable alerts before ${duration}, execute (as root or with sudo):
monitoringctl enable $1 --comment 'YOUR REASON'
EOF
echo -n "Confirm (y/N)? "
read -r answer
if [ "$answer" != "Y" ] && [ "$answer" != "y" ]; then
echo "Canceled."
exit 0
fi
log "Action disable $1 requested for ${duration} by user $(logname || echo unknown). Comment: '$2'"
# Log a warning if a check has no wrapper
if [ "$1" == "all" ]; then
checks=$(get_checks_list)
else
checks="$1"
fi
for check in ${checks}; do
command=$(get_check_commands "${check}" | tail -n1)
if ! echo "${command}" | grep --quiet --no-messages alerts_wrapper; then
log "Warning: check '${check}' has no alerts_wrapper, it will not be disabled."
fi
done
log "Executing 'alerts_switch disable $1 --during \"${duration}\"'"
alerts_switch disable "$1" --during "${duration}"
echo "$1 alerts are now disabled for ${duration}."
}
function enable {
# $1: check name, $2: comment
log "Action enable $1 requested by user $(logname || echo unknown). Comment: '$2'"
log "Executing 'alerts_switch enable $1'"
alerts_switch enable "$1"
echo "$1 alerts are now enabled."
}
### STATUS ACTION ##########################
# Converts human writable duration into seconds
function duration_to_seconds {
# $1: duration (XdYhZm…)
if echo "${1}" | grep -E -q '^([0-9]+[wdhms])+$'; then
echo "${1}" | sed 's/w/ * 604800 + /g; s/d/ * 86400 + /g; s/h/ * 3600 + /g; s/m/ * 60 + /g; s/s/ + /g; s/+ $//' | xargs expr
elif echo "${1}" | grep -E -q '^([0-9]+$)'; then
echo "${1} * 3600" | xargs expr
else
return 1
fi
}
# Converts seconds into human readable duration
function seconds_to_duration {
# $1: integer (seconds)
delay="$1"
delay_days="$(( delay /86400 ))"
if [ "${delay_days}" -eq 0 ]; then delay_days=""
else delay_days="${delay_days}d "; fi
delay_hours="$(( (delay %86400) /3600 ))"
if [ "${delay_hours}" -eq 0 ]; then delay_hours=""
else delay_hours="${delay_hours}h "; fi
delay_minutes="$(( ((delay %86400) %3600) /60 ))"
if [ "${delay_minutes}" -eq 0 ]; then delay_minutes=""
else delay_minutes="${delay_minutes}m "; fi
delay_seconds="$(( ((delay %86400) %3600) %60 ))"
if [ "${delay_seconds}" -eq 0 ]; then delay_seconds=""
else delay_seconds="${delay_seconds}s"; fi
echo "${delay_days}${delay_hours}${delay_minutes}${delay_seconds}"
}
function disabled_secs_left {
disabled_file="${base_dir}/all_alerts_disabled"
if [ ! -e "${disabled_file}" ]; then
echo 0
return
fi
disable_secs="$(grep -v -E "^\s*#" "${disabled_file}" | grep -E "[0-9]+" | head -n1 | awk '{print$1}')"
disable_date=$(date --date "${disable_secs} seconds ago" +"%s")
last_change=$(stat -c %Z "${disabled_file}")
echo $(( last_change - disable_date ))
}
function alerts_status {
echo "Not implemented yet"
exit 1
disabled_secs_left=$(disabled_secs_left)
disabled_duration_left="$(seconds_to_duration "${disabled_secs_left}")"
if [ -z "${disabled_duration_left}" ]; then
echo "All alerts are enabled."
else
disable_date=$(date --date "+${disabled_secs_left} seconds" "+%d %h %Y at %H:%M:%S")
echo "All alerts are still disabled for ${disabled_duration_left}."
echo "They will be re-enabled the ${disable_date}."
fi
}
### MAIN #########################################
# No root
if [ "$(id -u)" -ne 0 ]; then
>&2 echo "You need to be root (or use sudo) to run ${0}!"
exit 1
fi
# No argument
if [ "$#" = "0" ]; then
show_help
exit 1
fi
debian_major_version=$(cut -d "." -f 1 < /etc/debian_version)
conf_lines=$(get_conf_from_file "${conf_path}")
# Default arguments and options
action=""
comment=""
verbose="False"
duration="1h"
bypass_nrpe="False"
default_duration="True"
# Parse arguments and options
while :; do
case $1 in
-h|-\?|--help)
show_help
exit 0;;
-V|--version)
show_version
exit 0;;
-v|--verbose)
verbose="True"
shift;;
-b|--bypass-nrpe)
bypass_nrpe="True"
shift;;
-d|--during)
if [ "${default_duration}" = "False" ]; then
usage_error "Option --during: defined multiple times."
fi
if [ "$#" -gt 1 ]; then
if ! duration=$(filter_duration "$2"); then
exit 1
fi
default_duration="False"
else
usage_error "Option --during: missing value."
fi
shift; shift;;
-c|--comment)
if [ "$#" -gt 1 ]; then
comment="$2"
else
usage_error "Option --comment: missing comment string."
fi
shift; shift;;
status)
action="$1"
shift;;
check|enable|disable)
action="$1"
if [ "${action}" == "check" ]; then
names="$(get_checks_list)"
else
names="all $(get_wrappers_names)"
fi
if [ "$#" -gt 1 ]; then
if echo "${names}" | grep --quiet -E "^$2$"; then
check_name="$2"
shift; shift
else
usage_error "Action ${action}: unknown check '$2'."
fi
else
usage_error "Action ${action}: missing check argument."
fi
;;
*)
if [ -n "$1" ]; then
usage_error "Action '${action}': unknown argument '$1'."
else
break
fi
;;
esac
done
if [ "$#" -gt 0 ]; then
usage_error "Too many arguments."
fi
if [ -z "${action}" ]; then
usage_error "Missing or invalid ACTION argument."
fi
if [[ "${action}" =~ ((en|dis)able) ]]; then
if [ -z "${comment}" ]; then
usage_error "Action ${action}: missing --comment argument."
fi
fi
if [ ! "${action}" == "disable" ]; then
if [ "${default_duration}" = "False" ]; then
usage_error "Action ${action}: there is no --during option."
fi
fi
if [ "${action}" = "check" ]; then
check "${check_name}"
elif [ "${action}" = "enable" ]; then
enable "${check_name}" "${comment}"
elif [ "${action}" = "disable" ]; then
is_nrpe_wrapped
disable_alerts "${check_name}" "${comment}"
elif [ "${action}" = "status" ]; then
alerts_status
fi

View file

@ -0,0 +1,254 @@
#!/usr/bin/env bash
# Location of disable files
readonly var_dir="/var/lib/monitoringctl"
readonly log_file="/var/log/monitoringctl.log"
readonly nrpe_conf_path="/etc/nagios/nrpe.cfg"
debian_major_version="$(cut -d "." -f 1 < /etc/debian_version)"
readonly debian_major_version
# If no time limit is provided in CLI or found in file, this value is used
readonly default_disabled_time="1h"
function error() {
# $1: error message
>&2 echo "${1}"
exit 1
}
function usage_error() {
# $1: error message
>&2 echo "${1}"
>&2 echo "Execute \"${PROGNAME} --help\" for information on usage."
exit 1
}
function log() {
# $1: message
echo "$(now_iso) - ${PROGNAME}: ${1}" >> "${log_file}"
}
function show_version() {
cat <<END
${PROGNAME} version ${VERSION}.
Copyright 2018-2024 Evolix <info@evolix.fr>,
Jérémy Lecour <jlecour@evolix.fr>
and others.
${PROGNAME} comes with ABSOLUTELY NO WARRANTY.This is free software,
and you are welcome to redistribute it under certain conditions.
See the GNU General Public License v3.0 for details.
END
}
# Fail if argument does not respect format: XwXdXhXmXs, XhX, XmX
function filter_duration() {
# $1: duration in format specified above
time_regex="^([0-9]+d)?(([0-9]+h(([0-9]+m?)|([0-9]+m([0-9]+s?)?))?)|(([0-9]+m([0-9]+s?)?)?))?$"
if [[ "${1}" =~ ${time_regex} ]]; then
return 0
fi
return 1
}
# Convert human writable duration into seconds
function time_to_seconds() {
# $1: formated time string
if echo "${1}" | grep -E -q '^([0-9]+[wdhms])+$'; then
echo "${1}" | sed 's/w/ * 604800 + /g; s/d/ * 86400 + /g; s/h/ * 3600 + /g; s/m/ * 60 + /g; s/s/ + /g; s/+ $//' | xargs expr
elif echo "${1}" | grep -E -q '^([0-9]+h[0-9]+$)'; then
echo "${1}" | sed 's/h/ * 3600 + /g; s/$/ * 60/' | xargs expr
elif echo "${1}" | grep -E -q '^([0-9]+m[0-9]+$)'; then
echo "${1}" | sed 's/m/ * 60 + /g' | xargs expr
else
error "Invalid duration: '${1}'."
fi
}
# Print re-enable time in secs
function get_enable_time() {
# $1: wrapper name
disable_file_path="$(get_disable_file_path "${1}")"
enable_secs="$(grep -v -E "^\s*#" "${disable_file_path}" | grep -E "^[0-9]+$" | head -n1 | awk '{print $1}')"
# If file is empty, use file last change date plus default disabled time
if [ -z "${enable_secs}" ]; then
file_last_change_secs="$(stat -c %Z "${disable_file_path}")"
default_disabled_time_secs="$(time_to_seconds "${default_disabled_time}")"
enable_secs="$(( file_last_change_secs + default_disabled_time_secs ))"
fi
echo "${enable_secs}"
}
function now_secs() {
date +"%s"
}
function now_iso() {
date --iso-8601=seconds
}
# Print delay before re-enable in secs
function enable_delay() {
# $1: re-enable time in secs
#now_secs=$(date +"%s")
echo $(( ${1} - $(now_secs) ))
}
# Converts delay (in seconds) into human readable duration
function delay_to_string() {
# $1: delay in secs
delay_days="$(( ${1} /86400 ))"
if [ "${delay_days}" -eq 0 ]; then delay_days=""
else delay_days="${delay_days}d"; fi
delay_hours="$(( (${1} %86400) /3600 ))"
if [ "${delay_hours}" -eq 0 ]; then delay_hours=""
else delay_hours="${delay_hours}h"; fi
delay_minutes="$(( ((${1} %86400) %3600) /60 ))"
if [ "${delay_minutes}" -eq 0 ]; then delay_minutes=""
else delay_minutes="${delay_minutes}m"; fi
delay_seconds="$(( ((${1} %86400) %3600) %60 ))"
if [ "${delay_seconds}" -eq 0 ]; then delay_seconds=""
else delay_seconds="${delay_seconds}s"; fi
echo "${delay_days}${delay_hours}${delay_minutes}${delay_seconds}"
}
function is_disabled() {
# $1: wrapper name
disable_file_path="$(get_disable_file_path "${1}")"
if [ -e "${disable_file_path}" ]; then
enable_time="$(get_enable_time "${1}")"
enable_delay="$(enable_delay "${enable_time}")"
if [ "${enable_delay}" -le "0" ]; then
echo "False"
else
echo "True"
fi
else
echo False
fi
}
function get_disable_file_path() {
# $1: wrapper name
echo "${var_dir}/${1}_alerts_disabled"
}
### Nagios configuration functions ####################
# Print NRPE configuration, with includes, without comments
# and in the same order than NRPE does (taking account that
# order changes from Deb10)
function get_nrpe_conf() {
_get_conf_from_file "${nrpe_conf_path}"
}
# Private function to recursively get NRPE conf from file
function _get_conf_from_file() {
# $1: NRPE conf file (.cfg)
if [ ! -f "${1}" ]; then return; fi
conf_lines=$(grep -E -R -v --no-filename "^\s*(#.*|)$" "${1}")
while read -r line; do
if [[ "${line}" =~ .*'include='.* ]]; then
conf_file=$(echo "${line}" | cut -d= -f2)
_get_conf_from_file "${conf_file}"
elif [[ "${line}" =~ .*'include_dir='.* ]]; then
conf_dir=$(echo "${line}" | cut -d= -f2)
_get_conf_from_dir "${conf_dir}"
else
echo "${line}"
fi
done <<< "${conf_lines}"
}
# Private function to recursively get NRPE conf from directory
function _get_conf_from_dir() {
# $1: NRPE conf dir
if [ ! -d "${1}" ]; then return; fi
if [ "${debian_major_version}" -ge 10 ]; then
# From Deb10, NRPE use scandir() with alphasort() function
sort_command="sort"
else
# Before Deb10, NRPE use loaddir(), like find utility
sort_command="cat -"
fi
# Add conf files in dir to be processed recursively
for file in $(find "${1}" -maxdepth 1 -name "*.cfg" | ${sort_command}); do
if [ -f "${file}" ]; then
_get_conf_from_file "${file}"
elif [ -d "${file}" ]; then
_get_conf_from_dir "${file}"
fi
done
}
# Print the checks that are configured in NRPE
function get_checks_names() {
conf_lines="$(get_nrpe_conf "${nrpe_conf_path}")"
echo "${conf_lines}" | grep -E "command\[check_.*\]=" | awk -F"[\\\[\\\]=]" '{sub("check_", "", $2); print $2}' | sort | uniq
}
# Print the commands defined for check $1 in NRPE configuration
function get_check_commands() {
# $1: check name
conf_lines="$(get_nrpe_conf "${nrpe_conf_path}")"
echo "${conf_lines}" | grep -E "command\[check_${1}\]" | cut -d'=' -f2-
}
# Print the checks that have no alerts_wrapper in NRPE configuration
function not_wrapped_checks() {
for check in $(get_checks_names); do
if ! is_wrapped "${check}"; then
echo "${check}"
fi
done
}
# Fail if check is mot wrapped
function is_wrapped() {
# $1: check name
cmd=$(get_check_commands "${1}" | tail -n1)
if echo "${cmd}" | grep --quiet --no-messages alerts_wrapper; then
return 0
fi
return 1
}
# Print the names that are defined in the wrappers of the checks
function get_wrappers_names() {
conf_lines="$(get_nrpe_conf "${nrpe_conf_path}")"
echo "${conf_lines}" | grep -s "alerts_wrapper" | awk '{ for (i=1 ; i<=NF; i++) { if ($i ~ /^(-n|--name)$/) { print $(i+1); break } } }' | tr ',' '\n' | sort | uniq
}
function is_check() {
# $1: check name
checks="$(get_checks_names)"
if echo "${checks}" | grep --quiet -E "^${1}$"; then
return 0
fi
return 1
}
function is_wrapper() {
# $1: wrapper name
wrappers="$(get_wrappers_names)"
if echo "${wrappers}" | grep --quiet -E "^${1}$"; then
return 0
fi
return 1
}

View file

@ -1,18 +1,22 @@
#!/usr/bin/bash
#
_get_wrappers_names() {
grep "alerts_wrapper" -Rs /etc/nagios/ | grep -v -E "^\s*#" | awk '{ for (i=1 ; i<=NF; i++) { if ($i ~ /^(-n|--name)$/) { print $(i+1); break } } }' | tr ',' '\n' | sort | uniq
function _get_wrappers_names() {
grep "alerts_wrapper" --no-filename --no-messages -R /etc/nagios/ | grep --invert-match --extended-regexp "^\s*#" | awk '{ for (i=1 ; i<=NF; i++) { if ($i ~ /^(-n|--name)$/) { print $(i+1); break } } }' | tr ',' '\n' | sort | uniq
}
_monitoringctl_completion() {
function _get_checks_names() {
grep --extended-regexp --no-filename --no-messages -R "command\[check_.*\]=" /etc/nagios/ | grep --invert-match --extended-regexp "^\s*#" | awk -F"[\\\[\\\]=]" '{sub("check_", "", $2); print $2}' | sort | uniq
}
function _monitoringctl_completion() {
local cur=${COMP_WORDS[COMP_CWORD]};
local prev=${COMP_WORDS[COMP_CWORD-1]};
local action=""
for w in "${COMP_WORDS[@]}"; do
case "$w" in
status|check|enable|disable)
status|check|enable|disable|show)
action="${w}"
;;
esac
@ -20,12 +24,9 @@ _monitoringctl_completion() {
local words="--help"
case "${action}" in
status)
words="${words}"
;;
check)
local checks="$(_get_wrappers_names)"
local check=""
check|show)
checks="$(_get_checks_names)"
check=""
for w in "${COMP_WORDS[@]}"; do
for c in ${checks}; do
if [ "${c}" == "${w}" ]; then
@ -35,11 +36,17 @@ _monitoringctl_completion() {
done
done
if [ -z "${check}" ]; then
words="--bypass-nrpe ${checks} ${words}"
else
words="${checks} ${words}"
fi
if [ "${action}" == "check" ]; then
words="--bypass-nrpe ${words}"
fi
;;
status)
if [ "${prev}" == "enable" ]; then
words="all $(_get_checks_names)"
fi
;;
enable)
if [ "${prev}" == "enable" ]; then
words="all $(_get_wrappers_names)"
@ -57,7 +64,7 @@ _monitoringctl_completion() {
fi
;;
*)
words="status check enable disable ${words}"
words="status check enable disable show ${words}"
;;
esac
@ -77,5 +84,5 @@ _monitoringctl_completion() {
}
complete -F _monitoringctl_completion monitoringctl.sh
complete -F _monitoringctl_completion monitoringctl

View file

@ -1,16 +1,21 @@
---
- name: "Remount /usr if needed"
ansible.builtin.include_role:
name: remount-usr
- name: check if old script is present
- name: "dir /usr/local/lib/monitoringctl/ exists"
ansible.builtin.file:
path: /usr/local/lib/monitoringctl/
state: directory
mode: '0755'
- name: "check if old alerts_switch script is present"
ansible.builtin.stat:
path: /usr/share/scripts/alerts_switch
register: old_alerts_switch
- name: alerts_switch is at the right place
- name: "alerts_switch is at the right place"
ansible.builtin.command:
cmd: "mv /usr/share/scripts/alerts_switch /usr/local/bin/alerts_switch"
args:
@ -26,18 +31,64 @@
mode: "0750"
force: true
- name: "symlink for backward compatibility"
- name: "alerts_switch symlink for backward compatibility"
ansible.builtin.file:
src: /usr/local/bin/alerts_switch
dest: /usr/share/scripts/alerts_switch
path: /usr/share/scripts/alerts_switch
state: link
when: old_alerts_switch.stat.exists
- name: "check if old alerts_wrapper script is present"
ansible.builtin.stat:
path: "{{ nagios_plugins_directory }}/alerts_wrapper"
register: old_alerts_wrapper
- name: "alerts_wrapper is at the right place"
ansible.builtin.command:
cmd: "mv {{ nagios_plugins_directory }}/alerts_wrapper /usr/local/lib/monitoringctl/alerts_wrapper"
creates: /usr/local/lib/monitoringctl/alerts_wrapper
when: old_alerts_wrapper.stat.exists
- name: "copy alerts_wrapper"
ansible.builtin.copy:
src: alerts_wrapper
dest: "{{ nagios_plugins_directory }}/alerts_wrapper"
dest: "/usr/local/lib/monitoringctl/alerts_wrapper"
owner: root
group: staff
mode: "0755"
force: true
force: true
- name: "alerts_wrapper symlink for backward compatibility"
ansible.builtin.file:
src: /usr/local/lib/monitoringctl/alerts_wrapper
path: "{{ nagios_plugins_directory }}/alerts_wrapper"
state: link
when: old_alerts_wrapper.stat.exists
- name: "copy monitoringctl"
ansible.builtin.copy:
src: monitoringctl
dest: /usr/local/sbin/monitoringctl
owner: root
group: root
mode: "0750"
force: true
- name: "copy monitoringctl_common lib"
ansible.builtin.copy:
src: monitoringctl_common
dest: /usr/local/lib/monitoringctl/common
owner: root
group: root
mode: "0644"
force: true
- name: "copy monitoringctl_completion script"
ansible.builtin.copy:
src: monitoringctl_completion
dest: /etc/bash_completion.d/monitoringctl
owner: root
group: root
mode: "0644"
force: true