#!/bin/bash # Copyright (C) 2026 Cédric Abonnel # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. MONITORING_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" MONITORING_BASE_DIR="$(cd "${MONITORING_LIB_DIR}/.." && pwd)" MONITORING_CONF_DIR="${MONITORING_BASE_DIR}/conf" # Chargement config globale if [ -f "${MONITORING_CONF_DIR}/monitoring.conf" ]; then # shellcheck source=/dev/null . "${MONITORING_CONF_DIR}/monitoring.conf" fi SCRIPT_NAME="${SCRIPT_NAME:-$(basename "$0")}" SCRIPT_PATH="${SCRIPT_PATH:-$(readlink -f "$0" 2>/dev/null || realpath "$0" 2>/dev/null || echo "$0")}" STATUS_OK=0 STATUS_WARNING=1 STATUS_ERROR=2 STATUS_INTERNAL=3 CURRENT_STATUS=$STATUS_OK LOG_LEVEL=${LOG_LEVEL:-INFO} json_escape() { local s="${1:-}" s="${s//\\/\\\\}" s="${s//\"/\\\"}" s="${s//$'\n'/\\n}" s="${s//$'\r'/\\r}" s="${s//$'\t'/\\t}" printf '%s' "$s" } log_event() { local level="$1" local event="$2" local message="$3" shift 3 local ts extra key value kv host ts="$(date --iso-8601=seconds)" # Détection dynamique du hostname si HOSTNAME_FQDN n'est pas défini # On utilise 'hostname -f' pour le nom complet ou 'hostname' en secours host="${HOSTNAME_FQDN:-$(hostname -f 2>/dev/null || hostname)}" extra="" for kv in "$@"; do key="${kv%%=*}" value="${kv#*=}" extra="${extra},\"$(json_escape "$key")\":\"$(json_escape "$value")\"" done # Utilisation de la variable 'host' détectée ci-dessus printf '{"ts":"%s","host":"%s","app":"%s","level":"%s","event":"%s","message":"%s"%s}\n' \ "$(json_escape "$ts")" \ "$(json_escape "$host")" \ "$(json_escape "$SCRIPT_NAME")" \ "$(json_escape "$level")" \ "$(json_escape "$event")" \ "$(json_escape "$message")" \ "$extra" >> "${LOG_FILE:-/var/log/monitoring/events.jsonl}" } set_status() { local new_status="$1" if [ "$new_status" -gt "$CURRENT_STATUS" ]; then CURRENT_STATUS="$new_status" fi } log_debug() { log_event "DEBUG" "$@"; } log_info() { log_event "INFO" "$@"; } log_notice() { log_event "NOTICE" "$@"; } log_warning() { log_event "WARNING" "$@"; set_status "$STATUS_WARNING"; } log_error() { log_event "ERROR" "$@"; set_status "$STATUS_ERROR"; } log_critical() { log_event "CRITICAL" "$@"; set_status "$STATUS_ERROR"; } fail_internal() { log_event "ERROR" "internal_error" "$1" exit "$STATUS_INTERNAL" } exit_with_status() { exit "$CURRENT_STATUS" } require_cmd() { local cmd for cmd in "$@"; do command -v "$cmd" >/dev/null 2>&1 || fail_internal "Commande requise absente: $cmd" done } load_conf_if_exists() { local conf="$1" [ -f "$conf" ] && . "$conf" } lock_or_exit() { local lock_name="${1:-$SCRIPT_NAME}" local lock_file="${MONITORING_LOCK_DIR:-/var/lock/monitoring}/${lock_name}.lock" exec 9>"$lock_file" || fail_internal "Impossible d'ouvrir le lock $lock_file" flock -n 9 || { log_notice "already_running" "Une autre instance est déjà en cours" "lock=$lock_file" exit 0 } } threshold_level() { local value="$1" local warning="$2" local critical="$3" if [ "$value" -ge "$critical" ]; then printf 'CRITICAL' elif [ "$value" -ge "$warning" ]; then printf 'WARNING' else printf 'INFO' fi } safe_mv() { local src="$1" local dst="$2" mv -f "$src" "$dst" || fail_internal "Échec du déplacement de $src vers $dst" } ensure_parent_dir() { local file="$1" mkdir -p "$(dirname "$file")" || fail_internal "Impossible de créer le répertoire parent de $file" }