Compare commits
29 Commits
ae0c8f95cb
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e6263c1ae2 | |||
| 4e7119297c | |||
| 5e3b5ee741 | |||
| 95a6bb10b1 | |||
| 42626f2204 | |||
| ac6b80cb69 | |||
| 88b0dd4e77 | |||
| 365c8e543f | |||
| 61ebf5a92f | |||
| 12a7495447 | |||
| 7de4c86feb | |||
| d48cb923eb | |||
| 2540a96a1e | |||
| fba9bc89e2 | |||
| 312ba59343 | |||
| 78e2f5ea1e | |||
| 790052dfe5 | |||
| 8074151300 | |||
| b2c083eb8d | |||
| 8b52a02b55 | |||
| 0aebf47f6b | |||
| 6541cefea0 | |||
| 3b05390ec4 | |||
| 35f3c6f5f7 | |||
| 763bc0ba48 | |||
| c9d6fd48ed | |||
| 3fd1c70bd7 | |||
| c280e4d5ac | |||
| adfe0ed282 |
@@ -1,20 +1,20 @@
|
||||
# Lightweight Bash Monitoring System by Cédrix
|
||||
# 🛡️ PHP Monitoring System by Cédrix
|
||||
|
||||
Ce projet est une solution de monitoring légère, modulaire et auto-hébergée pour serveurs Linux. Elle permet de surveiller l'état des ressources (disque, RAM, etc.), de centraliser les logs au format JSON et d'envoyer des alertes via **ntfy** ou **email** avec un système de déduplication intelligent.
|
||||
Ce projet est une solution de monitoring **légère**, **modulaire** et **auto-hébergée** pour serveurs Linux. Elle combine la simplicité de sondes Bash avec la puissance d'un moteur de traitement PHP pour centraliser les logs et envoyer des alertes intelligentes via **ntfy** ou **email**.
|
||||
|
||||
## 🚀 Ce que fait ce système
|
||||
## 🚀 Fonctionnalités clés
|
||||
|
||||
* **Sondes modulaires :** Scripts indépendants pour vérifier les ressources (ex: `check_disk.sh`).
|
||||
* **Logs JSONL :** Centralisation de tous les événements dans `/var/log/monitoring/events.jsonl` pour une analyse facile.
|
||||
* **Moteur d'alerte :** Un moteur (`alert-engine.sh`) qui lit les logs en continu, gère les seuils de priorité et évite le spam grâce à une fenêtre de déduplication.
|
||||
* **Auto-update :** Capacité de se mettre à jour automatiquement depuis un dépôt Git via un manifeste.
|
||||
* **Robuste :** Gestion des verrous (locks) pour éviter que deux instances d'un même script ne tournent en même temps.
|
||||
* **Moteur PHP & Sondes Hybrides :** Traitement performant des alertes en PHP, tout en gardant des sondes système simples (Bash ou PHP).
|
||||
* **Alertes Intelligentes :** Envoi via **ntfy** (avec tags et priorités) ou **email**, incluant un système de **déduplication** pour éviter le spam.
|
||||
* **Logs JSONL :** Centralisation au format standard `JSON Lines` dans `/var/log/monitoring/events.jsonl` pour une exploitation facile.
|
||||
* **Configuration en cascade :** Système de fichiers `.local.conf.php` pour protéger vos réglages lors des mises à jour.
|
||||
* **Auto-update & Audit :** Mise à jour automatique via manifeste et script d'audit pour détecter les nouvelles options de configuration manquantes.
|
||||
|
||||
---
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
L'installation se fait via le script d'installation distant qui configure l'arborescence `/opt/monitoring`.
|
||||
L'installation se fait via un script Bash qui configure l'environnement et installe les dépendances nécessaires (PHP, curl).
|
||||
|
||||
```bash
|
||||
# Passer en root
|
||||
@@ -25,70 +25,65 @@ curl -sSL https://git.abonnel.fr/cedricAbonnel/scripts-bash/raw/branch/main/serv
|
||||
|
||||
```
|
||||
|
||||
### Arborescence créée :
|
||||
### Structure du système :
|
||||
|
||||
* `/opt/monitoring/bin/` : Scripts exécutables (sondes, moteur, updateur).
|
||||
* `/opt/monitoring/lib/` : Bibliothèque commune (`monitoring-lib.sh`).
|
||||
* `/opt/monitoring/conf/` : Fichiers de configuration.
|
||||
* `/var/log/monitoring/` : Logs des événements.
|
||||
* `/var/lib/monitoring/` : États (offsets de lecture, déduplication).
|
||||
* `/opt/monitoring/bin/` : Exécutables (sondes, moteur `alert-engine.php`, updater).
|
||||
* `/opt/monitoring/lib/` : Bibliothèque partagée (`monitoring-lib.php`).
|
||||
* `/opt/monitoring/conf/` : Fichiers de configuration PHP.
|
||||
* `/var/log/monitoring/` : Journal des événements (`events.jsonl`).
|
||||
* `/var/lib/monitoring/` : Index (offsets de lecture, états de déduplication).
|
||||
|
||||
---
|
||||
|
||||
## Configuration (Que modifier ?)
|
||||
## ⚙️ Configuration
|
||||
|
||||
Après l'installation, vous devez configurer vos accès pour recevoir les alertes.
|
||||
Le système utilise des fichiers PHP pour la configuration afin de permettre une logique dynamique.
|
||||
|
||||
### 1. Alertes (ntfy / Mail)
|
||||
|
||||
Éditez le fichier local (prioritaire sur la config par défaut) :
|
||||
`nano /opt/monitoring/conf/alert-engine.local.conf`
|
||||
Ne modifiez pas les fichiers `.conf.php` (risques d'écrasement). Créez vos fichiers locaux :
|
||||
`cp /opt/monitoring/conf/alert-engine.conf.php /opt/monitoring/conf/alert-engine.local.conf.php`
|
||||
|
||||
Modifiez les variables suivantes :
|
||||
Éditez le fichier local pour renseigner :
|
||||
|
||||
* `NTFY_TOKEN` : Votre jeton d'accès ntfy.
|
||||
* `NTFY_TOPIC` : Le nom de votre topic.
|
||||
* `DEST` : L'adresse email de réception.
|
||||
* `NTFY_TOKEN` & `NTFY_TOPIC`.
|
||||
* `DEST` (votre email de réception).
|
||||
|
||||
### 2. Seuils des sondes
|
||||
### 2. Audit de configuration
|
||||
|
||||
Vous pouvez modifier les variables `WARNING` et `CRITICAL` directement dans les scripts du dossier `bin/` ou, mieux, les définir dans `/opt/monitoring/conf/monitoring.local.conf`.
|
||||
Après une mise à jour, lancez l'outil d'audit pour vérifier si de nouvelles options sont disponibles :
|
||||
|
||||
---
|
||||
|
||||
## Programmation (Quand exécuter ?)
|
||||
|
||||
Le système repose sur `cron`. Voici la configuration recommandée à ajouter via `crontab -e` :
|
||||
|
||||
| Tâche | Fréquence | Commande |
|
||||
| --- | --- | --- |
|
||||
| **Check Disque** | Toutes les 5 min | `/opt/monitoring/bin/check_disk.sh` |
|
||||
| **Moteur d'alerte** | Toutes les 2 min | `/opt/monitoring/bin/alert-engine.sh` |
|
||||
| **Mise à jour** | Une fois par jour | `/opt/monitoring/bin/monitoring-update.sh` |
|
||||
|
||||
### Exemple de Crontab :
|
||||
|
||||
```cron
|
||||
*/5 * * * * /opt/monitoring/bin/check_disk.sh > /dev/null 2>&1
|
||||
*/2 * * * * /opt/monitoring/bin/alert-engine.sh > /dev/null 2>&1
|
||||
0 4 * * * /opt/monitoring/bin/monitoring-update.sh > /dev/null 2>&1
|
||||
```bash
|
||||
php /opt/monitoring/bin/monitoring-update-config.php
|
||||
|
||||
```
|
||||
|
||||
## Développer une nouvelle sonde
|
||||
---
|
||||
|
||||
Pour créer un nouveau check (ex: `check_ram.sh`) :
|
||||
## 🕒 Planification (Crontab)
|
||||
|
||||
1. Inclure la lib : `. /opt/monitoring/lib/monitoring-lib.sh`
|
||||
2. Effectuer votre mesure.
|
||||
3. Utiliser les fonctions de log : `log_info`, `log_warning` ou `log_critical`.
|
||||
4. Le moteur d'alerte détectera automatiquement le nouvel événement au prochain passage.
|
||||
Le système est conçu pour être piloté par `cron`. Voici la configuration recommandée :
|
||||
|
||||
| Tâche | Fréquence | Commande |
|
||||
| --- | --- | --- |
|
||||
| **Sondes (ex: Disque)** | Toutes les 5 min | `php /opt/monitoring/bin/check_disk.php` |
|
||||
| **Moteur d'alerte** | Chaque minute | `php /opt/monitoring/bin/alert-engine.php` |
|
||||
| **Mise à jour** | 1x par jour | `php /opt/monitoring/bin/monitoring-update.php` |
|
||||
|
||||
---
|
||||
|
||||
## Licence
|
||||
## 🛠️ Développer une nouvelle sonde
|
||||
|
||||
Ce projet est un logiciel libre : vous pouvez le redistribuer et le modifier selon les termes de la GNU Affero General Public License (AGPLv3) telle que publiée par la Free Software Foundation.
|
||||
Le système est agnostique. Pour ajouter un check :
|
||||
|
||||
Le code source modifié doit être mis à disposition si vous utilisez ce logiciel via un réseau (usage SaaS).
|
||||
1. Créez un script qui écrit une ligne JSON dans `/var/log/monitoring/events.jsonl`.
|
||||
2. Format attendu : `{"time":"...", "level":"ERROR", "app":"my_app", "event":"disk_full", "msg":"..."}`.
|
||||
3. Le moteur PHP `alert-engine.php` traitera l'alerte automatiquement au prochain passage.
|
||||
|
||||
---
|
||||
|
||||
## ⚖️ Licence
|
||||
|
||||
Ce projet est distribué sous licence **GNU Affero General Public License (AGPLv3)**.
|
||||
|
||||
*Note : Si vous modifiez ce code pour l'utiliser via un réseau (SaaS), vous devez rendre vos modifications publiques.*
|
||||
|
||||
81
servers/linux/monitoring/bin/alert-engine.php
Normal file → Executable file
81
servers/linux/monitoring/bin/alert-engine.php
Normal file → Executable file
@@ -9,7 +9,7 @@
|
||||
require_once __DIR__ . '/../lib/monitoring-lib.php';
|
||||
|
||||
// --- Initialisation de la configuration spécifique ---
|
||||
// On charge les fichiers de conf s'ils existent (format PHP attendu)
|
||||
// On charge les fichiers de conf s'ils existent
|
||||
foreach (["/opt/monitoring/conf/alert-engine.conf.php", "/opt/monitoring/conf/alert-engine.conf.local.php"] as $conf) {
|
||||
if (file_exists($conf)) {
|
||||
$extra_conf = include $conf;
|
||||
@@ -30,50 +30,97 @@ ensure_parent_dir($STATE_FILE);
|
||||
ensure_parent_dir($DEDUP_FILE);
|
||||
|
||||
/**
|
||||
* Nettoyage du fichier de déduplication (entrées expirées)
|
||||
* Nettoyage du fichier de déduplication
|
||||
* Supprime les entrées plus vieilles que la fenêtre de déduplication ($DEDUP_WINDOW)
|
||||
*/
|
||||
function cleanup_dedup_file() {
|
||||
global $DEDUP_FILE, $DEDUP_WINDOW;
|
||||
if (!file_exists($DEDUP_FILE)) return;
|
||||
|
||||
// Si le fichier n'existe pas, rien à nettoyer
|
||||
if (!file_exists($DEDUP_FILE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$lines = file($DEDUP_FILE, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
$kept = [];
|
||||
$has_changed = false;
|
||||
|
||||
// Lecture du fichier
|
||||
$lines = file($DEDUP_FILE, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
if ($lines === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$parts = explode('|', $line);
|
||||
if (count($parts) >= 2 && ($now - (int)$parts[1]) <= $DEDUP_WINDOW) {
|
||||
|
||||
// On vérifie si la ligne est valide et si le timestamp (index 1) est encore dans la fenêtre
|
||||
if (count($parts) >= 2) {
|
||||
$timestamp = (int)$parts[1];
|
||||
if (($now - $timestamp) <= (int)$DEDUP_WINDOW) {
|
||||
$kept[] = $line;
|
||||
} else {
|
||||
$has_changed = true; // On a trouvé au moins une ligne à supprimer
|
||||
}
|
||||
}
|
||||
file_put_contents($DEDUP_FILE, implode("\n", $kept) . (empty($kept) ? "" : "\n"));
|
||||
}
|
||||
|
||||
// On ne réécrit le fichier que si des lignes ont été supprimées
|
||||
if ($has_changed) {
|
||||
$content = implode("\n", $kept);
|
||||
if (!empty($content)) {
|
||||
$content .= "\n";
|
||||
}
|
||||
|
||||
// LOCK_EX évite que deux instances n'écrivent en même temps
|
||||
file_put_contents($DEDUP_FILE, $content, LOCK_EX);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si une alerte doit être envoyée (Déduplication)
|
||||
* La clé attendue est : "hostname|app|level|event"
|
||||
*/
|
||||
function should_notify_dedup($key) {
|
||||
function should_notify_dedup(string $key): bool {
|
||||
global $DEDUP_FILE, $DEDUP_WINDOW;
|
||||
if (!file_exists($DEDUP_FILE)) return true;
|
||||
|
||||
if (!file_exists($DEDUP_FILE)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$last_ts = 0;
|
||||
|
||||
$handle = fopen($DEDUP_FILE, 'r');
|
||||
if (!$handle) {
|
||||
return true; // En cas d'erreur de lecture, on autorise l'alerte par sécurité
|
||||
}
|
||||
|
||||
// On parcourt le fichier
|
||||
while (($line = fgets($handle)) !== false) {
|
||||
$p = explode('|', trim($line));
|
||||
$line = trim($line);
|
||||
if (empty($line)) continue;
|
||||
|
||||
$p = explode('|', $line);
|
||||
|
||||
// Format du fichier : host|timestamp|app|level|event
|
||||
// On reconstruit la clé de comparaison (sans le timestamp index 1)
|
||||
if (count($p) >= 5) {
|
||||
$current_key = "{$p[0]}|{$p[2]}|{$p[3]}|{$p[4]}";
|
||||
if ($current_key === $key) {
|
||||
$row_key = "{$p[0]}|{$p[2]}|{$p[3]}|{$p[4]}";
|
||||
|
||||
if ($row_key === $key) {
|
||||
$last_ts = (int)$p[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
|
||||
return ($now - $last_ts) >= $DEDUP_WINDOW;
|
||||
// Calcul de l'écart : vrai si on a dépassé la fenêtre ou si jamais vu (last_ts = 0)
|
||||
return ($now - $last_ts) >= (int)$DEDUP_WINDOW;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Envoi vers ntfy
|
||||
*/
|
||||
@@ -123,26 +170,28 @@ function send_mail($subject, $body) {
|
||||
* Traitement d'une ligne de log
|
||||
*/
|
||||
function process_line($line) {
|
||||
global $CONFIG, $DEDUP_FILE;
|
||||
global $CONFIG, $DEDUP_FILE;
|
||||
$data = json_decode($line, true);
|
||||
if (!$data || !isset($data['level'], $data['event'])) return;
|
||||
|
||||
$level = strtoupper($data['level']);
|
||||
$event = $data['event'];
|
||||
|
||||
if (in_array($level, ['DEBUG', 'INFO', 'NOTICE'])) return;
|
||||
// On garde uniquement l'ignore list explicite pour les événements
|
||||
if (in_array($event, ($CONFIG['ALERT_IGNORE_EVENTS'] ?? []))) return;
|
||||
|
||||
// Déduplication
|
||||
$key = "{$data['host']}|{$data['app']}|{$level}|{$event}";
|
||||
if (!should_notify_dedup($key)) {
|
||||
log_debug("alert_suppressed_dedup", "Alerte dédupliquée", ["event=$event", "host={$data['host']}"]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Détermination des canaux (Règle spécifique puis défaut)
|
||||
// Détermination des canaux
|
||||
$channels_str = $CONFIG['RULES'][$event] ?? $CONFIG['DEFAULT_CHANNELS'][$level] ?? '';
|
||||
|
||||
// Si aucun canal n'est défini pour ce niveau, ALORS on s'arrête
|
||||
if (empty($channels_str)) return;
|
||||
|
||||
$channels = explode(',', $channels_str);
|
||||
|
||||
$title = "{$data['host']} [{$data['app']}] $level $event";
|
||||
|
||||
@@ -13,41 +13,49 @@
|
||||
|
||||
set -u
|
||||
|
||||
. /opt/monitoring/lib/monitoring-lib.sh || exit 3
|
||||
|
||||
# --- Configuration (Seuils par défaut) ---
|
||||
WARNING=80
|
||||
CRITICAL=95
|
||||
MOUNTS=("/" "/var" "/home")
|
||||
LOG_BIN="/opt/monitoring/bin/log-cli.php"
|
||||
|
||||
# --- Vérification ROOT ---
|
||||
if [ "${EUID}" -ne 0 ]; then
|
||||
echo "ERREUR : Ce script doit être exécuté en tant que root." >&2
|
||||
$LOG_BIN ERROR "internal_error" "Tentative d'exécution sans privilèges root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for mount in "${MOUNTS[@]}"; do
|
||||
# On vérifie si le point de montage existe avant de tester
|
||||
if ! mountpoint -q "$mount"; then
|
||||
continue
|
||||
fi
|
||||
if ! mountpoint -q "$mount"; then continue; fi
|
||||
|
||||
# --- 1. Espace Disque ---
|
||||
used_pct="$(df -P "$mount" 2>/dev/null | awk 'NR==2 {gsub("%","",$5); print $5}')"
|
||||
|
||||
if [[ ! "$used_pct" =~ ^[0-9]+$ ]]; then
|
||||
log_error "check_failed" "Impossible de lire l'utilisation disque" "mount=$mount"
|
||||
continue
|
||||
$LOG_BIN ERROR "check_failed" "Erreur lecture disque $mount."
|
||||
else
|
||||
if [ "$used_pct" -ge "$CRITICAL" ]; then
|
||||
$LOG_BIN CRITICAL "disk_usage_critical" "Disque $mount critique : $used_pct% utilisé."
|
||||
elif [ "$used_pct" -ge "$WARNING" ]; then
|
||||
$LOG_BIN WARNING "disk_usage_high" "Disque $mount élevé : $used_pct% utilisé."
|
||||
else
|
||||
$LOG_BIN INFO "disk_ok" "Disque $mount OK : $used_pct% utilisé."
|
||||
fi
|
||||
fi
|
||||
|
||||
level="$(threshold_level "$used_pct" "$WARNING" "$CRITICAL")"
|
||||
# --- 2. Inodes (Déplacé à l'intérieur de la boucle) ---
|
||||
inode_pct="$(df -iP "$mount" 2>/dev/null | awk 'NR==2 {gsub("%","",$5); print $5}')"
|
||||
|
||||
case "$level" in
|
||||
INFO)
|
||||
log_info "disk_ok" "Utilisation disque normale" \
|
||||
"mount=$mount" "used_pct=$used_pct" "warning=$WARNING" "critical=$CRITICAL"
|
||||
;;
|
||||
WARNING)
|
||||
log_warning "disk_usage_high" "Utilisation disque élevée" \
|
||||
"mount=$mount" "used_pct=$used_pct" "warning=$WARNING" "critical=$CRITICAL"
|
||||
;;
|
||||
CRITICAL)
|
||||
log_critical "disk_usage_critical" "Utilisation disque critique" \
|
||||
"mount=$mount" "used_pct=$used_pct" "warning=$WARNING" "critical=$CRITICAL"
|
||||
;;
|
||||
esac
|
||||
if [[ ! "$inode_pct" =~ ^[0-9]+$ ]]; then
|
||||
$LOG_BIN ERROR "check_failed" "Erreur lecture inodes $mount."
|
||||
else
|
||||
if [ "$inode_pct" -ge "$CRITICAL" ]; then
|
||||
$LOG_BIN CRITICAL "inode_usage_critical" "Inodes $mount critiques ($inode_pct%)."
|
||||
elif [ "$inode_pct" -ge "$WARNING" ]; then
|
||||
$LOG_BIN WARNING "inode_usage_high" "Inodes $mount élevés ($inode_pct%)."
|
||||
else
|
||||
$LOG_BIN INFO "inode_ok" "Inodes $mount OK ($inode_pct%)."
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
exit_with_status
|
||||
66
servers/linux/monitoring/bin/check_smart.sh
Executable file
66
servers/linux/monitoring/bin/check_smart.sh
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# 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.
|
||||
|
||||
LOG_BIN="/opt/monitoring/bin/log-cli.php"
|
||||
|
||||
# --- Vérification ROOT ---
|
||||
if [ "${EUID}" -ne 0 ]; then
|
||||
echo "ERREUR : Ce script doit être exécuté en tant que root." >&2
|
||||
$LOG_BIN ERROR "internal_error" "Tentative d'exécution sans privilèges root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Vérification et installation de smartctl ---
|
||||
if ! command -v smartctl >/dev/null 2>&1; then
|
||||
# On tente l'installation (nécessite root, ce qui est le cas via cron)
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
apt-get update && apt-get install -y smartmontools
|
||||
fi
|
||||
|
||||
# Re-vérification après tentative
|
||||
if ! command -v smartctl >/dev/null 2>&1; then
|
||||
$LOG_BIN ERROR "internal_error" "smartctl non trouvé et installation impossible."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# On récupère les disques qui ont un transport physique (SATA, NVMe, USB)
|
||||
# Cela exclut d'office les /dev/mapper, /dev/dm-X, /dev/loopX
|
||||
DISKS=$(lsblk -dno NAME,TRAN | awk '$2!="" {print "/dev/"$1}')
|
||||
|
||||
for disk in $DISKS; do
|
||||
# Vérification : est-ce que smartctl peut lire ce périphérique ?
|
||||
# --scan-open vérifie si le disque est capable de répondre
|
||||
if ! smartctl -i "$disk" | grep -q "SMART support is: Enabled" 2>/dev/null; then
|
||||
# On peut logguer en INFO que le disque est ignoré car non-SMART (ex: clé USB basique)
|
||||
continue
|
||||
fi
|
||||
|
||||
# 1. État de santé global
|
||||
smart_output=$(smartctl -H "$disk" 2>/dev/null)
|
||||
exit_code=$?
|
||||
|
||||
if [ $exit_code -ne 0 ]; then
|
||||
$LOG_BIN CRITICAL "smart_health_bad" "État de santé PHYSIQUE CRITIQUE sur $disk"
|
||||
else
|
||||
# 2. Température
|
||||
temp=$(smartctl -A "$disk" 2>/dev/null | awk '/Temperature_Celsius/ {print $10}' | head -n 1)
|
||||
[ -z "$temp" ] && temp=$(smartctl -a "$disk" 2>/dev/null | awk '/Temperature:/ {print $2}' | head -n 1)
|
||||
|
||||
if [ -n "$temp" ]; then
|
||||
if [ "$temp" -ge 60 ]; then
|
||||
$LOG_BIN WARNING "disk_temp_high" "Surchauffe physique sur $disk : ${temp}°C"
|
||||
fi
|
||||
fi
|
||||
$LOG_BIN INFO "smart_health_ok" "Disque physique $disk sain."
|
||||
fi
|
||||
done
|
||||
@@ -11,51 +11,51 @@ LOG_DIR="/var/log/monitoring"
|
||||
STATE_DIR="/var/lib/monitoring"
|
||||
LOCK_DIR="/var/lock/monitoring"
|
||||
TMP_DIR="/tmp/monitoring-install"
|
||||
# Journal des fichiers installés pour déinstallation/état des lieux
|
||||
INSTALLED_LOG="${STATE_DIR}/installed-files.log"
|
||||
|
||||
UPDATE_BASE_URL="https://git.abonnel.fr/cedricAbonnel/scripts-bash/raw/branch/main/servers/linux/monitoring"
|
||||
MANIFEST_URL="${UPDATE_BASE_URL}/manifest.txt"
|
||||
|
||||
INSTALL_DEPS="${INSTALL_DEPS:-true}"
|
||||
|
||||
# --- Fonctions ---
|
||||
# --- Fonctions d'affichage ---
|
||||
info() { echo -e "\e[34m[INFO]\e[0m $1"; }
|
||||
ok() { echo -e "\e[32m[OK]\e[0m $1"; }
|
||||
warn() { echo -e "\e[33m[WARN]\e[0m $1"; }
|
||||
err() { echo -e "\e[31m[ERR]\e[0m $1"; }
|
||||
|
||||
# --- Fonctions Techniques ---
|
||||
|
||||
require_root() {
|
||||
if [ "${EUID}" -ne 0 ]; then
|
||||
echo "ERREUR: Ce script doit être exécuté en root." >&2
|
||||
err "Ce script doit être exécuté en root."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
install_deps() {
|
||||
if [ "${INSTALL_DEPS}" != "true" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "--- Installation des dépendances ---"
|
||||
if [ "${INSTALL_DEPS}" != "true" ]; then return 0; fi
|
||||
info "Vérification des dépendances système..."
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
apt-get update
|
||||
apt-get install -y curl coreutils findutils grep sed gawk util-linux ca-certificates
|
||||
# Ajout des modules PHP nécessaires pour vos scripts (curl pour ntfy)
|
||||
apt-get install -y php-cli php-curl php-common
|
||||
else
|
||||
echo "AVERTISSEMENT: Gestionnaire de paquets apt non détecté. Assurez-vous que php-cli et php-curl sont installés."
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq curl coreutils findutils grep sed gawk util-linux ca-certificates php-cli php-curl php-common smartmontools > /dev/null
|
||||
ok "Dépendances installées."
|
||||
fi
|
||||
}
|
||||
|
||||
prepare_dirs() {
|
||||
echo "--- Préparation des répertoires ---"
|
||||
info "Préparation de l'arborescence dans ${BASE_DIR}..."
|
||||
mkdir -p "${BASE_DIR}/bin" "${BASE_DIR}/lib" "${CONF_DIR}" "${LOG_DIR}" "${STATE_DIR}" "${LOCK_DIR}" "${TMP_DIR}"
|
||||
chmod 755 "${BASE_DIR}" "${CONF_DIR}" "${LOG_DIR}" "${STATE_DIR}" "${LOCK_DIR}"
|
||||
touch "$INSTALLED_LOG"
|
||||
}
|
||||
|
||||
fetch_manifest() {
|
||||
echo "--- Récupération du manifeste ---"
|
||||
info "Téléchargement du manifeste distant..."
|
||||
curl -fsS "${MANIFEST_URL}" -o "${TMP_DIR}/manifest.txt"
|
||||
}
|
||||
|
||||
validate_manifest() {
|
||||
# Validation du format : Hash Mode Chemin
|
||||
# Exemple : a1b2... 755 bin/script.php
|
||||
awk '
|
||||
NF == 3 &&
|
||||
$1 ~ /^[0-9a-fA-F]{64}$/ &&
|
||||
@@ -65,35 +65,32 @@ validate_manifest() {
|
||||
' "${TMP_DIR}/manifest.txt"
|
||||
}
|
||||
|
||||
download_one() {
|
||||
local expected_hash="$1"
|
||||
local mode="$2"
|
||||
local rel_path="$3"
|
||||
|
||||
local url="${UPDATE_BASE_URL}/${rel_path}"
|
||||
download_and_install() {
|
||||
local expected_hash=$1 mode=$2 rel_path=$3
|
||||
local dst="${BASE_DIR}/${rel_path}"
|
||||
|
||||
# On ignore le téléchargement si c'est un fichier de conf qui existe déjà
|
||||
if [[ "$rel_path" == conf/* ]] && [ -f "$dst" ]; then
|
||||
echo "Skip: $rel_path (existe déjà)"
|
||||
return 0
|
||||
if [ -f "$dst" ]; then
|
||||
local current_hash
|
||||
current_hash=$(sha256sum "$dst" | awk '{print $1}')
|
||||
[ "$current_hash" == "$expected_hash" ] && return 0
|
||||
info "Mise à jour : $rel_path"
|
||||
else
|
||||
info "Installation : $rel_path"
|
||||
fi
|
||||
|
||||
echo "Téléchargement: $rel_path"
|
||||
local tmp_file
|
||||
tmp_file="$(mktemp "${TMP_DIR}/file.XXXXXX")"
|
||||
|
||||
if ! curl -fsS "$url" -o "$tmp_file"; then
|
||||
echo "ERREUR: Échec du téléchargement de ${url}" >&2
|
||||
if ! curl -fsS "${UPDATE_BASE_URL}/${rel_path}" -o "$tmp_file"; then
|
||||
err "Échec du téléchargement pour $rel_path"
|
||||
rm -f "$tmp_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local got_hash
|
||||
got_hash="$(sha256sum "$tmp_file" | awk '{print $1}')"
|
||||
|
||||
got_hash=$(sha256sum "$tmp_file" | awk '{print $1}')
|
||||
if [ "$got_hash" != "$expected_hash" ]; then
|
||||
echo "ERREUR: Hash invalide pour ${rel_path}" >&2
|
||||
err "Hash invalide pour $rel_path"
|
||||
rm -f "$tmp_file"
|
||||
return 1
|
||||
fi
|
||||
@@ -103,34 +100,45 @@ download_one() {
|
||||
chmod "$mode" "$dst"
|
||||
}
|
||||
|
||||
install_from_manifest() {
|
||||
echo "--- Installation des fichiers ---"
|
||||
while read -r hash mode rel_path; do
|
||||
[ -n "${hash:-}" ] || continue
|
||||
download_one "$hash" "$mode" "$rel_path"
|
||||
done < "${TMP_DIR}/manifest-valid.txt"
|
||||
# --- NOUVEAUTÉ : Gestion du journal et purge propre ---
|
||||
|
||||
update_installed_log() {
|
||||
# On sauvegarde la liste des chemins relatifs du manifeste validé dans le journal permanent
|
||||
awk '{print $3}' "${TMP_DIR}/manifest-valid.txt" > "$INSTALLED_LOG"
|
||||
ok "Journal des fichiers déployés mis à jour ($INSTALLED_LOG)."
|
||||
}
|
||||
|
||||
show_next_steps() {
|
||||
cat <<EOF
|
||||
purge_obsolete_files() {
|
||||
info "Analyse des fichiers obsolètes (Synchronisation avec le journal)..."
|
||||
|
||||
Installation terminée avec succès dans ${BASE_DIR}.
|
||||
# On compare ce qui était installé (journal) avec ce qui est dans le nouveau manifeste
|
||||
if [ ! -s "$INSTALLED_LOG" ]; then
|
||||
warn "Journal vide, passage en mode scan classique."
|
||||
# Fallback sur le scan de dossier si le journal n'existe pas encore
|
||||
find "${BASE_DIR}/bin" "${BASE_DIR}/lib" "${BASE_DIR}/conf" -type f 2>/dev/null | while read -r local_file; do
|
||||
local rel_path="${local_file#$BASE_DIR/}"
|
||||
[[ "$rel_path" == *".local."* ]] && continue
|
||||
if ! grep -qw "$rel_path" "${TMP_DIR}/manifest-valid.txt"; then
|
||||
warn "Suppression : $rel_path"
|
||||
rm -f "$local_file"
|
||||
fi
|
||||
done
|
||||
return
|
||||
fi
|
||||
|
||||
Étapes suivantes :
|
||||
1. Configurez vos alertes :
|
||||
cp ${CONF_DIR}/alert-engine.conf.php ${CONF_DIR}/alert-engine.local.conf.php
|
||||
nano ${CONF_DIR}/alert-engine.local.conf.php
|
||||
|
||||
2. Initialisez la configuration globale :
|
||||
cp ${CONF_DIR}/monitoring.conf.php ${CONF_DIR}/monitoring.local.conf.php
|
||||
|
||||
3. Lancez un audit des configurations :
|
||||
php ${BASE_DIR}/bin/monitoring-update-config.php
|
||||
|
||||
4. Planifiez les tâches (cron) :
|
||||
*/5 * * * * php ${BASE_DIR}/bin/alert-engine.php
|
||||
10 3 * * * php ${BASE_DIR}/bin/monitoring-update.php
|
||||
EOF
|
||||
# Mode Journal : On lit l'ancien journal pour voir ce qui doit disparaître
|
||||
while read -r old_file; do
|
||||
# Si le fichier du journal n'est plus dans le nouveau manifeste
|
||||
if ! grep -qw "$old_file" "${TMP_DIR}/manifest-valid.txt"; then
|
||||
if [ -f "${BASE_DIR}/$old_file" ]; then
|
||||
# Protection ultime des fichiers .local (au cas où ils auraient été loggués par erreur)
|
||||
if [[ "$old_file" != *".local."* ]]; then
|
||||
warn "Suppression du fichier obsolète : $old_file"
|
||||
rm -f "${BASE_DIR}/$old_file"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done < "$INSTALLED_LOG"
|
||||
}
|
||||
|
||||
# --- Main ---
|
||||
@@ -142,16 +150,38 @@ main() {
|
||||
fetch_manifest
|
||||
|
||||
if ! validate_manifest > "${TMP_DIR}/manifest-valid.txt"; then
|
||||
echo "ERREUR: Le manifeste est invalide ou corrompu." >&2
|
||||
err "Le manifeste est invalide ou corrompu."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install_from_manifest
|
||||
echo "--------------------------------------------------"
|
||||
info "Phase 1 : Installation et mises à jour"
|
||||
while read -r hash mode rel_path; do
|
||||
[ -n "${hash:-}" ] || continue
|
||||
download_and_install "$hash" "$mode" "$rel_path"
|
||||
done < "${TMP_DIR}/manifest-valid.txt"
|
||||
|
||||
echo "--------------------------------------------------"
|
||||
info "Phase 2 : Nettoyage et Journalisation"
|
||||
purge_obsolete_files
|
||||
update_installed_log
|
||||
|
||||
# Nettoyage
|
||||
rm -rf "${TMP_DIR}"
|
||||
echo "--------------------------------------------------"
|
||||
ok "Opération terminée avec succès."
|
||||
|
||||
show_next_steps
|
||||
# --- Vérification de la configuration ---
|
||||
local_conf="${CONF_DIR}/monitoring.local.conf.php"
|
||||
orig_conf="${CONF_DIR}/monitoring.conf.php"
|
||||
|
||||
if [ -f "$local_conf" ] && [ -f "$orig_conf" ]; then
|
||||
if [ "$(sha256sum "$local_conf" | awk '{print $1}')" == "$(sha256sum "$orig_conf" | awk '{print $1}')" ]; then
|
||||
echo -e "\n\e[33m[ATTENTION]\e[0m Votre fichier de configuration est identique à l'original."
|
||||
warn "Pensez à éditer ${local_conf}."
|
||||
else
|
||||
ok "Configuration locale personnalisée détectée."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
23
servers/linux/monitoring/bin/log-cli.php
Executable file
23
servers/linux/monitoring/bin/log-cli.php
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* Pont de logging pour scripts Bash
|
||||
*/
|
||||
require_once __DIR__ . '/../lib/monitoring-lib.php';
|
||||
|
||||
if ($argc < 4) {
|
||||
fwrite(STDERR, "Usage: log-cli.php <LEVEL> <EVENT> <MESSAGE> [CONTEXT...]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$level = strtoupper($argv[1]);
|
||||
$event = $argv[2];
|
||||
$message = $argv[3];
|
||||
$context = [];
|
||||
|
||||
// On récupère les arguments restants comme contexte
|
||||
for ($i = 4; $i < $argc; $i++) {
|
||||
$context[] = $argv[$i];
|
||||
}
|
||||
|
||||
log_event($level, $event, $message, $context);
|
||||
0
servers/linux/monitoring/bin/monitoring-update-config.php
Normal file → Executable file
0
servers/linux/monitoring/bin/monitoring-update-config.php
Normal file → Executable file
360
servers/linux/monitoring/bin/monitoring-update.php
Normal file → Executable file
360
servers/linux/monitoring/bin/monitoring-update.php
Normal file → Executable file
@@ -1,219 +1,179 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* Moteur de mise à jour des programmes
|
||||
* Moteur de mise à jour
|
||||
* Pilotage du script Bash + Initialisation des Configs + Cron + Ménage
|
||||
* Copyright (C) 2026 Cédric Abonnel
|
||||
* License: GNU Affero General Public License v3
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../lib/monitoring-lib.php';
|
||||
|
||||
// --- Chargement de la configuration spécifique ---
|
||||
foreach (["/opt/monitoring/conf/autoupdate.conf.php", "/opt/monitoring/conf/autoupdate.local.conf.php"] as $conf) {
|
||||
if (file_exists($conf)) {
|
||||
$extra_conf = include $conf;
|
||||
if (is_array($extra_conf)) {
|
||||
$CONFIG = array_replace_recursive($CONFIG, $extra_conf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Variables par défaut
|
||||
$UPDATE_ENABLED = $CONFIG['UPDATE_ENABLED'] ?? true;
|
||||
$UPDATE_TMP_DIR = $CONFIG['UPDATE_TMP_DIR'] ?? '/tmp/monitoring-update';
|
||||
$UPDATE_TIMEOUT_CONNECT = $CONFIG['UPDATE_TIMEOUT_CONNECT'] ?? 3;
|
||||
$UPDATE_TIMEOUT_TOTAL = $CONFIG['UPDATE_TIMEOUT_TOTAL'] ?? 15;
|
||||
$UPDATE_MANIFEST_URL = $CONFIG['UPDATE_MANIFEST_URL'] ?? '';
|
||||
$UPDATE_BASE_URL = $CONFIG['UPDATE_BASE_URL'] ?? '';
|
||||
$UPDATE_ALLOW_DELETE = $CONFIG['UPDATE_ALLOW_DELETE'] ?? false;
|
||||
|
||||
// Sécurité
|
||||
// Sécurité : Un seul update à la fois
|
||||
lock_or_exit("monitoring-update");
|
||||
|
||||
if (!$UPDATE_ENABLED) {
|
||||
log_notice("update_disabled", "Mise à jour désactivée par configuration");
|
||||
exit(0);
|
||||
echo "\e[1m--- Début de la mise à jour système ---\e[0m\n";
|
||||
|
||||
// 1. Avant l'update, on mémorise la liste des fichiers actuellement installés (L'AVANT)
|
||||
$installed_log = $CONFIG['INSTALLED_LOG'] ?? '/var/lib/monitoring/installed-files.log';
|
||||
$old_installed_files = [];
|
||||
if (file_exists($installed_log)) {
|
||||
$old_installed_files = file($installed_log, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
}
|
||||
|
||||
if (!is_dir($UPDATE_TMP_DIR)) {
|
||||
mkdir($UPDATE_TMP_DIR, 0755, true);
|
||||
// 2. Exécution du moteur de synchronisation Bash
|
||||
$install_script = __DIR__ . '/install-monitoring.sh';
|
||||
|
||||
if (!file_exists($install_script)) {
|
||||
log_error("update_script_missing", "Script d'installation introuvable", ["path" => $install_script]);
|
||||
echo "\e[31m[ERR]\e[0m Script d'installation introuvable : $install_script\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Télécharge et valide le manifeste
|
||||
*/
|
||||
function fetch_manifest() {
|
||||
global $UPDATE_MANIFEST_URL, $UPDATE_TIMEOUT_TOTAL;
|
||||
// Exécution du moteur de synchronisation Bash
|
||||
$command = "bash " . escapeshellarg($install_script) . " --auto 2>&1";
|
||||
$handle = popen($command, 'r');
|
||||
|
||||
$content = @file_get_contents($UPDATE_MANIFEST_URL, false, stream_context_create([
|
||||
'http' => ['timeout' => $UPDATE_TIMEOUT_TOTAL]
|
||||
]));
|
||||
|
||||
if ($content === false) {
|
||||
log_error("manifest_download_failed", "Impossible de télécharger le manifeste", ["url=$UPDATE_MANIFEST_URL"]);
|
||||
return false;
|
||||
if ($handle) {
|
||||
while (!feof($handle)) {
|
||||
$line = fgets($handle);
|
||||
if ($line) echo $line;
|
||||
}
|
||||
|
||||
$lines = explode("\n", trim($content));
|
||||
$manifest_data = [];
|
||||
|
||||
foreach ($lines as $line) {
|
||||
if (empty(trim($line))) continue;
|
||||
|
||||
$parts = preg_split('/\s+/', trim($line));
|
||||
if (count($parts) !== 3) continue;
|
||||
|
||||
list($hash, $mode, $path) = $parts;
|
||||
|
||||
// Validation stricte (Regex identique au Bash)
|
||||
if (preg_match('/^[0-9a-f]{64}$/i', $hash) &&
|
||||
preg_match('/^(644|755)$/', $mode) &&
|
||||
preg_match('/^(bin|lib|conf)\/[A-Za-z0-9._\/-]+$/', $path) &&
|
||||
strpos($path, '..') === false) {
|
||||
$manifest_data[] = ['hash' => strtolower($hash), 'mode' => $mode, 'path' => $path];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($manifest_data)) {
|
||||
log_error("manifest_invalid", "Le manifeste distant est vide ou invalide");
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("manifest_downloaded", "Manifeste téléchargé", ["url=$UPDATE_MANIFEST_URL"]);
|
||||
return $manifest_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mise à jour d'un fichier unique
|
||||
*/
|
||||
function update_one_file($expected_hash, $mode, $rel_path) {
|
||||
global $MONITORING_BASE_DIR, $UPDATE_BASE_URL, $UPDATE_TMP_DIR, $UPDATE_TIMEOUT_TOTAL;
|
||||
|
||||
$local_file = $MONITORING_BASE_DIR . '/' . $rel_path;
|
||||
$remote_url = rtrim($UPDATE_BASE_URL, '/') . '/' . $rel_path;
|
||||
$tmp_file = $UPDATE_TMP_DIR . '/' . basename($rel_path) . '.' . bin2hex(random_bytes(4));
|
||||
|
||||
$local_hash = file_exists($local_file) ? hash_file('sha256', $local_file) : null;
|
||||
|
||||
if ($local_hash === $expected_hash) {
|
||||
log_debug("update_not_needed", "Fichier déjà à jour", ["file=$rel_path"]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Téléchargement via cURL pour gérer les timeouts proprement
|
||||
$ch = curl_init($remote_url);
|
||||
$fp = fopen($tmp_file, 'w');
|
||||
curl_setopt($ch, CURLOPT_FILE, $fp);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $UPDATE_TIMEOUT_TOTAL);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
$success = curl_exec($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
fclose($fp);
|
||||
|
||||
if (!$success || $http_code !== 200) {
|
||||
log_error("update_download_failed", "Téléchargement impossible", ["file=$rel_path", "url=$remote_url"]);
|
||||
@unlink($tmp_file);
|
||||
return false;
|
||||
}
|
||||
|
||||
$downloaded_hash = hash_file('sha256', $tmp_file);
|
||||
if ($downloaded_hash !== $expected_hash) {
|
||||
log_error("update_hash_mismatch", "Hash téléchargé invalide", ["file=$rel_path", "expected=$expected_hash", "got=$downloaded_hash"]);
|
||||
@unlink($tmp_file);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Installation
|
||||
ensure_parent_dir($local_file);
|
||||
chmod($tmp_file, ($mode == '755' ? 0755 : 0644));
|
||||
|
||||
if (rename($tmp_file, $local_file)) {
|
||||
if (!$local_hash) {
|
||||
log_notice("file_created", "Fichier créé", ["file=$rel_path", "mode=$mode"]);
|
||||
} else {
|
||||
log_notice("update_applied", "Mise à jour appliquée", ["file=$rel_path", "new_hash=$expected_hash"]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suppression des fichiers obsolètes
|
||||
*/
|
||||
function delete_extra_files($manifest_paths) {
|
||||
global $UPDATE_ALLOW_DELETE, $MONITORING_BASE_DIR;
|
||||
if (!$UPDATE_ALLOW_DELETE) return;
|
||||
|
||||
$dirs = ['bin', 'lib', 'conf'];
|
||||
foreach ($dirs as $dir) {
|
||||
$full_dir = $MONITORING_BASE_DIR . '/' . $dir;
|
||||
if (!is_dir($full_dir)) continue;
|
||||
|
||||
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($full_dir));
|
||||
foreach ($iterator as $file) {
|
||||
if ($file->isDir()) continue;
|
||||
|
||||
$rel_path = str_replace($MONITORING_BASE_DIR . '/', '', $file->getPathname());
|
||||
|
||||
// Protection des .local.conf
|
||||
if (str_ends_with($rel_path, '.local.conf') || str_ends_with($rel_path, '.local.php')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!in_array($rel_path, $manifest_paths)) {
|
||||
if (@unlink($file->getPathname())) {
|
||||
log_notice("file_deleted", "Fichier obsolète supprimé", ["file=$rel_path"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lancement du script de synchronisation local
|
||||
*/
|
||||
function run_local_conf_sync() {
|
||||
global $MONITORING_BASE_DIR;
|
||||
$sync_script = $MONITORING_BASE_DIR . '/bin/monitoring-update-config.sh'; // On cherche la version PHP
|
||||
|
||||
if (file_exists($sync_script)) {
|
||||
log_info("local_conf_sync_start", "Synchronisation des configs locales");
|
||||
passthru("php " . escapeshellarg($sync_script), $return_var);
|
||||
if ($return_var !== 0) {
|
||||
log_warning("local_conf_sync_failed", "Échec de synchronisation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Exécution principale ---
|
||||
|
||||
$manifest = fetch_manifest();
|
||||
if (!$manifest) exit(2);
|
||||
|
||||
$total = count($manifest);
|
||||
$updated = 0;
|
||||
$failed = 0;
|
||||
$remote_paths = [];
|
||||
|
||||
foreach ($manifest as $item) {
|
||||
$remote_paths[] = $item['path'];
|
||||
if (update_one_file($item['hash'], $item['mode'], $item['path'])) {
|
||||
$updated++;
|
||||
} else {
|
||||
$failed++;
|
||||
}
|
||||
}
|
||||
|
||||
delete_extra_files($remote_paths);
|
||||
run_local_conf_sync();
|
||||
|
||||
if ($failed > 0) {
|
||||
log_warning("update_finished_with_errors", "Mise à jour terminée avec erreurs", ["total=$total", "failed=$failed"]);
|
||||
$exit_code = pclose($handle);
|
||||
} else {
|
||||
log_info("update_finished", "Mise à jour terminée", ["total=$total", "checked=$updated"]);
|
||||
$exit_code = 1;
|
||||
}
|
||||
|
||||
exit_with_status();
|
||||
if ($exit_code !== 0) {
|
||||
log_error("update_failed", "Le script Bash a échoué");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// 3. Après l'update, on récupère la nouvelle liste (L'APRÈS)
|
||||
$new_installed_files = [];
|
||||
if (file_exists($installed_log)) {
|
||||
$new_installed_files = file($installed_log, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
}
|
||||
|
||||
// Détermination des fichiers qui ont été SUPPRIMÉS lors de cette mise à jour (dynamique)
|
||||
$deleted_files = array_diff($old_installed_files, $new_installed_files);
|
||||
|
||||
echo "\e[1m--- Finalisation des configurations ---\e[0m\n";
|
||||
ensure_local_configs();
|
||||
ensure_crontab_entries($deleted_files);
|
||||
|
||||
echo "\e[32m[OK]\e[0m Système à jour.\n";
|
||||
|
||||
/**
|
||||
* Nettoyage et Mise à jour du Crontab
|
||||
* @param array $deleted_files Liste des chemins de fichiers supprimés du déploiement
|
||||
*/
|
||||
function ensure_crontab_entries($deleted_files) {
|
||||
global $CONFIG, $MONITORING_BASE_DIR;
|
||||
|
||||
// --- CONFIGURATION DU MÉNAGE STATIQUE ---
|
||||
// On ajoute ici les vieux chemins orphelins à éjecter impérativement
|
||||
$static_cleanup_patterns = [
|
||||
'/usr/local/bin/sys_check.sh',
|
||||
'bin/check_disk.php', // Ancienne erreur de nommage
|
||||
'bin/check-disk.sh' // Ancienne erreur de séparateur
|
||||
];
|
||||
|
||||
// Préparation des jobs requis
|
||||
$required_jobs = array_map(function($job) use ($MONITORING_BASE_DIR) {
|
||||
return str_replace('{BASE_DIR}', $MONITORING_BASE_DIR, $job);
|
||||
}, $CONFIG['CRON_JOBS'] ?? [
|
||||
"*/5 * * * * bash {$MONITORING_BASE_DIR}/bin/check_disk.sh > /dev/null 2>&1",
|
||||
"*/15 * * * * bash {$MONITORING_BASE_DIR}/bin/check_smart.sh > /dev/null 2>&1",
|
||||
"10 3 * * * php {$MONITORING_BASE_DIR}/bin/monitoring-update.php > /dev/null 2>&1",
|
||||
"* * * * * php {$MONITORING_BASE_DIR}/bin/alert-engine.php > /dev/null 2>&1"
|
||||
]);
|
||||
|
||||
$current_cron = shell_exec("crontab -l 2>/dev/null") ?: "";
|
||||
$lines = explode("\n", trim($current_cron));
|
||||
$new_lines = [];
|
||||
$has_changed = false;
|
||||
|
||||
// --- PHASE A : Nettoyage (Dynamique + Statique) ---
|
||||
foreach ($lines as $line) {
|
||||
$trim_line = trim($line);
|
||||
if (empty($trim_line)) continue;
|
||||
|
||||
$keep = true;
|
||||
|
||||
// 1. Nettoyage Dynamique (basé sur le log Git)
|
||||
foreach ($deleted_files as $deleted_path) {
|
||||
if (strpos($trim_line, $deleted_path) !== false) {
|
||||
echo "\e[33m[CLEAN]\e[0m Script supprimé du déploiement : " . basename($deleted_path) . "\n";
|
||||
$keep = false;
|
||||
$has_changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Nettoyage Statique (basé sur ta liste forcée)
|
||||
if ($keep) {
|
||||
foreach ($static_cleanup_patterns as $pattern) {
|
||||
if (strpos($trim_line, $pattern) !== false) {
|
||||
echo "\e[33m[CLEAN]\e[0m Suppression du résidu historique : $pattern\n";
|
||||
$keep = false;
|
||||
$has_changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($keep) $new_lines[] = $trim_line;
|
||||
}
|
||||
|
||||
// --- PHASE B : Ajout des nouveaux jobs ---
|
||||
foreach ($required_jobs as $job) {
|
||||
// Extraction du chemin du script pour éviter les doublons
|
||||
preg_match('/\/bin\/([a-z0-9_-]+\.(php|sh))/i', $job, $matches);
|
||||
$script_path = $matches[0] ?? "";
|
||||
|
||||
$found = false;
|
||||
foreach ($new_lines as $line) {
|
||||
if (strpos($line, $script_path) !== false) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found && !empty($script_path)) {
|
||||
$new_lines[] = $job;
|
||||
$has_changed = true;
|
||||
echo "\e[32m[OK]\e[0m Ajout au cron : " . basename($script_path) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// --- PHASE C : Application ---
|
||||
if ($has_changed) {
|
||||
$content = implode("\n", array_filter($new_lines, 'trim')) . "\n";
|
||||
$tmp_cron = tempnam(sys_get_temp_dir(), 'cron');
|
||||
file_put_contents($tmp_cron, $content);
|
||||
exec("crontab " . escapeshellarg($tmp_cron));
|
||||
unlink($tmp_cron);
|
||||
echo "\e[32m[OK]\e[0m Crontab synchronisé.\n";
|
||||
} else {
|
||||
echo "[INFO] Crontab déjà à jour.\n";
|
||||
}
|
||||
}
|
||||
|
||||
function ensure_local_configs() {
|
||||
global $MONITORING_CONF_DIR;
|
||||
$configs = [
|
||||
'monitoring.conf.php' => 'monitoring.local.conf.php',
|
||||
'alert-engine.conf.php' => 'alert-engine.conf.local.php',
|
||||
'autoupdate.conf.php' => 'autoupdate.local.conf.php'
|
||||
];
|
||||
foreach ($configs as $src => $dst) {
|
||||
$dst_path = $MONITORING_CONF_DIR . '/' . $dst;
|
||||
if (!file_exists($dst_path)) {
|
||||
$src_path = $MONITORING_CONF_DIR . '/' . $src;
|
||||
if (file_exists($src_path)) {
|
||||
copy($src_path, $dst_path);
|
||||
chmod($dst_path, 0600);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
145
servers/linux/monitoring/bin/monitoring.php
Normal file → Executable file
145
servers/linux/monitoring/bin/monitoring.php
Normal file → Executable file
@@ -8,9 +8,8 @@
|
||||
require_once __DIR__ . '/../lib/monitoring-lib.php';
|
||||
|
||||
// --- Configuration ---
|
||||
// On s'appuie sur le chargement de la lib, mais on surcharge si nécessaire
|
||||
$conf_file = "/opt/monitoring/conf/autoupdate.conf.php"; // Format PHP recommandé
|
||||
// --- Chargement de la configuration spécifique ---
|
||||
// Note : La lib a déjà chargé $CONFIG['UPDATE_BASE_URL'] etc. depuis monitoring.local.conf.php
|
||||
// On ne charge les fichiers spécifiques que s'ils apportent des règles de mise à jour uniques.
|
||||
foreach (["/opt/monitoring/conf/autoupdate.conf.php", "/opt/monitoring/conf/autoupdate.local.conf.php"] as $conf) {
|
||||
if (file_exists($conf)) {
|
||||
$extra_conf = include $conf;
|
||||
@@ -20,28 +19,25 @@ foreach (["/opt/monitoring/conf/autoupdate.conf.php", "/opt/monitoring/conf/auto
|
||||
}
|
||||
}
|
||||
|
||||
// Variables par défaut
|
||||
// Variables par défaut (fallback si absent de la config globale)
|
||||
$UPDATE_ENABLED = $CONFIG['UPDATE_ENABLED'] ?? true;
|
||||
$UPDATE_TMP_DIR = $CONFIG['UPDATE_TMP_DIR'] ?? '/tmp/monitoring-update';
|
||||
$UPDATE_TIMEOUT_CONNECT = $CONFIG['UPDATE_TIMEOUT_CONNECT'] ?? 3;
|
||||
$UPDATE_TIMEOUT_TOTAL = $CONFIG['UPDATE_TIMEOUT_TOTAL'] ?? 15;
|
||||
$UPDATE_MANIFEST_URL = $CONFIG['UPDATE_MANIFEST_URL'] ?? '';
|
||||
$UPDATE_BASE_URL = $CONFIG['UPDATE_BASE_URL'] ?? '';
|
||||
$UPDATE_ALLOW_DELETE = $CONFIG['UPDATE_ALLOW_DELETE'] ?? false;
|
||||
$MONITORING_BASE_DIR = $CONFIG['MONITORING_BASE_DIR'] ?? '/opt/monitoring';
|
||||
$MONITORING_BASE_DIR = $MONITORING_BASE_DIR; // Provient de la lib
|
||||
|
||||
// --- Initialisation ---
|
||||
lock_or_exit("monitoring-update");
|
||||
|
||||
if (!$UPDATE_ENABLED) {
|
||||
log_notice("update_disabled", "Mise à jour désactivée par configuration");
|
||||
log_notice("update_disabled", "Mise à jour désactivée");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!is_dir($UPDATE_TMP_DIR)) {
|
||||
if (!mkdir($UPDATE_TMP_DIR, 0755, true)) {
|
||||
fail_internal("Impossible de créer le répertoire temporaire: $UPDATE_TMP_DIR");
|
||||
}
|
||||
mkdir($UPDATE_TMP_DIR, 0755, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,13 +47,16 @@ function fetch_manifest($url) {
|
||||
global $UPDATE_TIMEOUT_TOTAL;
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $UPDATE_TIMEOUT_TOTAL);
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, true);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => $UPDATE_TIMEOUT_TOTAL,
|
||||
CURLOPT_FAILONERROR => true,
|
||||
CURLOPT_FOLLOWLOCATION => true
|
||||
]);
|
||||
|
||||
$content = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
log_error("manifest_download_failed", "Impossible de télécharger le manifeste", ["url" => $url, "error" => curl_error($ch)]);
|
||||
log_error("manifest_download_failed", "Échec téléchargement manifeste", ["url" => $url, "err" => curl_error($ch)]);
|
||||
return false;
|
||||
}
|
||||
curl_close($ch);
|
||||
@@ -66,30 +65,15 @@ function fetch_manifest($url) {
|
||||
$lines = explode("\n", trim($content));
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
if (empty($line)) continue;
|
||||
|
||||
// Validation format: hash(64) mode(3) path
|
||||
if (preg_match('/^([0-9a-fA-F]{64})\s+(644|755)\s+((bin|lib|conf)\/[A-Za-z0-9._\/-]+)$/', $line, $matches)) {
|
||||
$manifest_entries[] = [
|
||||
'hash' => $matches[1],
|
||||
'mode' => $matches[2],
|
||||
'path' => $matches[3]
|
||||
];
|
||||
if (preg_match('/^([0-9a-fA-F]{64})\s+(644|755)\s+((bin|lib|conf)\/[A-Za-z0-9._\/-]+)$/', trim($line), $matches)) {
|
||||
$manifest_entries[] = ['hash' => $matches[1], 'mode' => $matches[2], 'path' => $matches[3]];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($manifest_entries)) {
|
||||
log_error("manifest_invalid", "Le manifeste distant est invalide ou vide", ["url" => $url]);
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("manifest_downloaded", "Manifeste téléchargé", ["url" => $url]);
|
||||
return $manifest_entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour un fichier spécifique
|
||||
* Met à jour un fichier
|
||||
*/
|
||||
function update_one_file($entry) {
|
||||
global $MONITORING_BASE_DIR, $UPDATE_BASE_URL, $UPDATE_TMP_DIR, $UPDATE_TIMEOUT_TOTAL;
|
||||
@@ -99,129 +83,86 @@ function update_one_file($entry) {
|
||||
$remote_url = rtrim($UPDATE_BASE_URL, '/') . '/' . $rel_path;
|
||||
$expected_hash = strtolower($entry['hash']);
|
||||
|
||||
// Calcul du hash local actuel
|
||||
$local_hash = file_exists($target_file) ? hash_file('sha256', $target_file) : "";
|
||||
|
||||
if ($local_hash === $expected_hash) {
|
||||
log_debug("update_not_needed", "Fichier déjà à jour", ["file" => $rel_path]);
|
||||
if (file_exists($target_file) && hash_file('sha256', $target_file) === $expected_hash) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Téléchargement
|
||||
$tmp_file = $UPDATE_TMP_DIR . '/' . basename($rel_path) . '.' . uniqid();
|
||||
$ch = curl_init($remote_url);
|
||||
$fp = fopen($tmp_file, 'wb');
|
||||
|
||||
curl_setopt($ch, CURLOPT_FILE, $fp);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $UPDATE_TIMEOUT_TOTAL);
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, true);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_FILE => $fp,
|
||||
CURLOPT_TIMEOUT => $UPDATE_TIMEOUT_TOTAL,
|
||||
CURLOPT_FAILONERROR => true,
|
||||
CURLOPT_FOLLOWLOCATION => true
|
||||
]);
|
||||
|
||||
$success = curl_exec($ch);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
fclose($fp);
|
||||
|
||||
if (!$success) {
|
||||
log_error("update_download_failed", "Téléchargement impossible", ["file" => $rel_path, "url" => $remote_url, "error" => $error]);
|
||||
if (!$success || hash_file('sha256', $tmp_file) !== $expected_hash) {
|
||||
log_error("update_failed", "Fichier invalide ou corrompu", ["file" => $rel_path]);
|
||||
@unlink($tmp_file);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Vérification Hash
|
||||
$downloaded_hash = hash_file('sha256', $tmp_file);
|
||||
if ($downloaded_hash !== $expected_hash) {
|
||||
log_error("update_hash_mismatch", "Hash téléchargé invalide", ["file" => $rel_path, "expected" => $expected_hash, "got" => $downloaded_hash]);
|
||||
@unlink($tmp_file);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Installation
|
||||
ensure_parent_dir($target_file);
|
||||
chmod($tmp_file, octdec($entry['mode']));
|
||||
safe_mv($tmp_file, $target_file); // Utilise la fonction safe_mv de ta lib
|
||||
|
||||
if (!rename($tmp_file, $target_file)) {
|
||||
fail_internal("Échec du déplacement de $tmp_file vers $target_file");
|
||||
}
|
||||
|
||||
if ($local_hash === "") {
|
||||
log_notice("file_created", "Fichier créé depuis le manifeste", ["file" => $rel_path, "mode" => $entry['mode']]);
|
||||
} else {
|
||||
log_notice("update_applied", "Mise à jour appliquée", ["file" => $rel_path, "old_hash" => $local_hash, "new_hash" => $expected_hash]);
|
||||
}
|
||||
|
||||
log_notice("file_updated", "Mise à jour appliquée", ["file" => $rel_path]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime les fichiers locaux absents du manifeste
|
||||
* Nettoyage
|
||||
*/
|
||||
function delete_extra_files($remote_files) {
|
||||
global $UPDATE_ALLOW_DELETE, $MONITORING_BASE_DIR;
|
||||
global $UPDATE_ALLOW_DELETE, $MONITORING_BASE_DIR, $SCRIPT_PATH;
|
||||
if (!$UPDATE_ALLOW_DELETE) return;
|
||||
|
||||
$directories = ['bin', 'lib', 'conf'];
|
||||
foreach ($directories as $dir) {
|
||||
foreach (['bin', 'lib', 'conf'] as $dir) {
|
||||
$full_path = $MONITORING_BASE_DIR . '/' . $dir;
|
||||
if (!is_dir($full_path)) continue;
|
||||
|
||||
$iterator = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($full_path, RecursiveDirectoryIterator::SKIP_DOTS)
|
||||
);
|
||||
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($full_path, RecursiveDirectoryIterator::SKIP_DOTS));
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
// On récupère le chemin relatif par rapport à la racine du monitoring
|
||||
$rel_path = substr($file->getPathname(), strlen($MONITORING_BASE_DIR) + 1);
|
||||
$path = $file->getPathname();
|
||||
$rel_path = substr($path, strlen($MONITORING_BASE_DIR) + 1);
|
||||
|
||||
// 1. Protection : Si c'est dans le manifeste distant, on ne touche à rien
|
||||
if (in_array($rel_path, $remote_files)) {
|
||||
continue;
|
||||
}
|
||||
// PROTECTIONS
|
||||
if (in_array($rel_path, $remote_files)) continue;
|
||||
if (str_contains($rel_path, '.local.')) continue; // Protection fichiers locaux
|
||||
if ($path === $SCRIPT_PATH) continue; // Ne pas se suicider
|
||||
|
||||
// 2. Protection générique : On n'efface JAMAIS les fichiers de configuration locale
|
||||
// Cela couvre : *.local.conf.php, *.local.conf, et même *.local.php par sécurité
|
||||
if (str_ends_with($rel_path, '.local.conf.php') ||
|
||||
str_ends_with($rel_path, '.local.conf') ||
|
||||
str_ends_with($rel_path, '.local.php')) {
|
||||
|
||||
log_debug("delete_skipped", "Fichier local protégé (ignoré)", ["file" => $rel_path]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3. Suppression si le fichier est obsolète et non protégé
|
||||
if (@unlink($file->getPathname())) {
|
||||
if (@unlink($path)) {
|
||||
log_notice("file_deleted", "Fichier obsolète supprimé", ["file" => $rel_path]);
|
||||
} else {
|
||||
log_error("delete_failed", "Impossible de supprimer le fichier local", ["file" => $rel_path]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Main ---
|
||||
|
||||
$manifest = fetch_manifest($UPDATE_MANIFEST_URL);
|
||||
if ($manifest === false) exit(2);
|
||||
if (!$manifest) exit(2);
|
||||
|
||||
$total = count($manifest);
|
||||
$updated = 0;
|
||||
$failed = 0;
|
||||
$remote_paths = [];
|
||||
$updated = 0; $failed = 0;
|
||||
|
||||
foreach ($manifest as $entry) {
|
||||
$remote_paths[] = $entry['path'];
|
||||
if (update_one_file($entry)) {
|
||||
$updated++;
|
||||
} else {
|
||||
$failed++;
|
||||
}
|
||||
update_one_file($entry) ? $updated++ : $failed++;
|
||||
}
|
||||
|
||||
delete_extra_files($remote_paths);
|
||||
|
||||
if ($failed > 0) {
|
||||
log_warning("update_finished_with_errors", "Mise à jour terminée avec erreurs", ["total" => $total, "updated" => $updated, "failed" => $failed]);
|
||||
log_warning("update_partial", "Mise à jour terminée avec erreurs", ["failed" => $failed]);
|
||||
} else {
|
||||
log_info("update_finished", "Mise à jour terminée", ["total" => $total, "updated" => $updated]);
|
||||
log_info("update_ok", "Mise à jour terminée avec succès");
|
||||
}
|
||||
|
||||
exit_with_status();
|
||||
@@ -24,12 +24,6 @@ return [
|
||||
'ALERT_MAIL_SUBJECT_PREFIX' => '[monitoring]',
|
||||
'DEST' => 'admin@example.com', // N'oubliez pas de définir le destinataire
|
||||
|
||||
// --- Configuration ntfy ---
|
||||
'NTFY_SERVER' => 'https://ntfy.sh',
|
||||
'NTFY_TOPIC' => 'TPOSOB84sBJ6HTZ7',
|
||||
'NTFY_TOKEN' => '',
|
||||
'NTFY_CLICK_URL' => '',
|
||||
|
||||
// --- Déduplication ---
|
||||
'ALERT_DEDUP_WINDOW' => 3600, // en secondes
|
||||
|
||||
@@ -42,16 +36,25 @@ return [
|
||||
|
||||
// --- Canaux par défaut selon le niveau ---
|
||||
'DEFAULT_CHANNELS' => [
|
||||
'INFO' => 'ntfy',
|
||||
'NOTICE' => 'ntfy',
|
||||
'WARNING' => 'ntfy',
|
||||
'ERROR' => 'ntfy,mail',
|
||||
'CRITICAL' => 'ntfy,mail',
|
||||
],
|
||||
|
||||
// --- Tags ntfy par niveau ---
|
||||
// --- Tags : Une icône pour chaque état possible ---
|
||||
'NTFY_TAGS' => [
|
||||
'WARNING' => 'warning',
|
||||
'ERROR' => 'warning,rotating_light',
|
||||
'CRITICAL' => 'skull,warning',
|
||||
'DEBUG' => 'gear', // ⚙️
|
||||
'INFO' => 'information_source', // ℹ️
|
||||
'NOTICE' => 'bell', // 🔔
|
||||
'SUCCESS' => 'white_check_mark', // ✅
|
||||
'WARNING' => 'warning', // ⚠️
|
||||
'ERROR' => 'rotating_light,warning', // 🚨
|
||||
'CRITICAL' => 'skull,warning', // 💀
|
||||
'ALERT' => 'ambulance,rotating_light',// 🚑
|
||||
'EMERGENCY' => 'fire,sos,skull', // 🔥
|
||||
'AUDIT' => 'mag', // 🔍
|
||||
],
|
||||
|
||||
// --- Règles spécifiques par événement ---
|
||||
|
||||
@@ -51,4 +51,13 @@ return [
|
||||
|
||||
// --- Logs ---
|
||||
'LOG_LEVEL' => 'INFO', // DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL
|
||||
|
||||
'STATE_DIR' => '/var/lib/monitoring',
|
||||
'INSTALLED_LOG' => '/var/lib/monitoring/installed-files.log',
|
||||
'CRON_JOBS' => [
|
||||
"*/5 * * * * bash {BASE_DIR}/bin/check_disk.sh > /dev/null 2>&1",
|
||||
"*/15 * * * * bash {BASE_DIR}/bin/check_smart.sh > /dev/null 2>&1",
|
||||
"10 3 * * * php {BASE_DIR}/bin/monitoring-update.php > /dev/null 2>&1",
|
||||
"* * * * * php {BASE_DIR}/bin/alert-engine.php > /dev/null 2>&1"
|
||||
],
|
||||
];
|
||||
@@ -25,11 +25,16 @@ $CONFIG = [
|
||||
'LOG_LEVEL' => 'INFO'
|
||||
];
|
||||
|
||||
if (file_exists($MONITORING_CONF_DIR . '/monitoring.conf.php')) {
|
||||
$global_conf = include $MONITORING_CONF_DIR . '/monitoring.conf.php';
|
||||
if (is_array($global_conf)) {
|
||||
$CONFIG = array_merge($CONFIG, $global_conf);
|
||||
}
|
||||
// 1. On charge la configuration GLOBALE (La vérité est ici)
|
||||
$global_conf = $MONITORING_CONF_DIR . "/monitoring.local.conf.php";
|
||||
if (file_exists($global_conf)) {
|
||||
$CONFIG = array_replace_recursive($CONFIG, include $global_conf);
|
||||
}
|
||||
|
||||
// 2. On charge ensuite la config spécifique au script (si besoin de surcharger)
|
||||
// $specific_conf est défini par le script qui appelle la lib
|
||||
if (isset($specific_conf) && file_exists($specific_conf)) {
|
||||
$CONFIG = array_replace_recursive($CONFIG, include $specific_conf);
|
||||
}
|
||||
|
||||
// Variables d'exécution
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
f433b3e2ca25c76cccebf971072255dae64169a8ae162d6baa10776904d733e9 755 bin/alert-engine.sh
|
||||
7ff2eb1163ca8b9aa3927ac7f0ebbcc1f90c944e51afbc880d57359b83a0c73f 755 bin/check_disk.sh
|
||||
4fae83b48dc25c5e2a59bba944d8c3f2c6dff89bf2adb932d4dd9201f6305ca4 755 bin/install-monitoring.sh
|
||||
36528963f2e78a160738a2cf3b8da67b9d12dbe495d9d01ca6c1ba97956288fa 755 bin/monitoring.sh
|
||||
78ccebfd1da7cf885fddb8d5a967c23e379c495d8f43490584ace7133690ec55 755 bin/monitoring-update.sh
|
||||
54eb520360c80b3146c5cdb846330a8743cbeb9fe6de0559357114b92d090c29 755 bin/monitor-update-config.sh
|
||||
83db39c8d0cfd6f6e9d3cc5b961a67db29dc73666304a91e0d4a6d5831c623cb 644 conf/alert-engine.conf
|
||||
caaa8f6031d66bc43a897ac2804124ce2050a64523734195d5505ae863836bf4 644 conf/monitoring.conf
|
||||
654cd98ecda1c485a0ea1224f160a3c4d7396ab95a491603574e2ad1981fe010 644 lib/monitoring-lib.sh
|
||||
5b4ea784d2cbe73f6e829e35f23b0b4dbe12df55cc1abc8eba6602da36c724ef 755 bin/alert-engine.php
|
||||
fdcea6720186795538f48c08b99103b320273dbdd0ea5246a2da9d81a1eecc6c 755 bin/check_disk.sh
|
||||
ead10d3be3aac48c6406a734dee1bddf9a8abb1e21de102ce72fa92fdecbaf22 755 bin/check_smart.sh
|
||||
8f95824b568b5de7dbdc2d6ab87fc6fd8076dcb8ad20de3e72a53391e97f8484 755 bin/install-monitoring.sh
|
||||
97a91b13b0776acb3326010821ffcc163e96a97e3c326ea77f11efdb7baf159a 755 bin/log-cli.php
|
||||
02bd43ed2a9b92acc013274c716e6bc50120a8103ccf3d9c4e6f345a0b22d6a0 755 bin/monitoring.php
|
||||
97d407d75a26bd2ebbb86a2e5f8dab8b24639e8a9164f42bd554ba7728ab8cb5 755 bin/monitoring-update-config.php
|
||||
910a7c3a4423fb5456233d0c6cbcfc7f511c94947580972c42286762142e5ce6 755 bin/monitoring-update.php
|
||||
dc70c1184da4aa32eebdeaee57cfed23e91397c94a6243e0ac8664968078f0c7 644 conf/alert-engine.conf.php
|
||||
324038d28f24f3f4d1f6def73752ff703d4ce8b532a663c6628611923748b1f5 644 conf/monitoring.conf.php
|
||||
9bb7f5438edc5fb6a5b899ee21be2a5a559eb0697a028a4e991fc82362eaa460 644 lib/monitoring-lib.php
|
||||
|
||||
Reference in New Issue
Block a user