187 lines
6.0 KiB
Bash
Executable File
187 lines
6.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# Copyright (C) 2026 Cédric Abonnel
|
|
# License: GNU Affero General Public License v3
|
|
|
|
set -euo pipefail
|
|
|
|
# --- Configuration ---
|
|
BASE_DIR="/opt/monitoring"
|
|
CONF_DIR="${BASE_DIR}/conf"
|
|
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 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
|
|
err "Ce script doit être exécuté en root."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
install_deps() {
|
|
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 -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() {
|
|
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}"
|
|
touch "$INSTALLED_LOG"
|
|
}
|
|
|
|
fetch_manifest() {
|
|
info "Téléchargement du manifeste distant..."
|
|
curl -fsS "${MANIFEST_URL}" -o "${TMP_DIR}/manifest.txt"
|
|
}
|
|
|
|
validate_manifest() {
|
|
awk '
|
|
NF == 3 &&
|
|
$1 ~ /^[0-9a-fA-F]{64}$/ &&
|
|
$2 ~ /^(644|755|600)$/ &&
|
|
$3 ~ /^(bin|lib|conf)\/[A-Za-z0-9._\/-]+$/ &&
|
|
$3 !~ /\.\./
|
|
' "${TMP_DIR}/manifest.txt"
|
|
}
|
|
|
|
download_and_install() {
|
|
local expected_hash=$1 mode=$2 rel_path=$3
|
|
local dst="${BASE_DIR}/${rel_path}"
|
|
|
|
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
|
|
|
|
local tmp_file
|
|
tmp_file="$(mktemp "${TMP_DIR}/file.XXXXXX")"
|
|
|
|
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}')
|
|
if [ "$got_hash" != "$expected_hash" ]; then
|
|
err "Hash invalide pour $rel_path"
|
|
rm -f "$tmp_file"
|
|
return 1
|
|
fi
|
|
|
|
mkdir -p "$(dirname "$dst")"
|
|
mv -f "$tmp_file" "$dst"
|
|
chmod "$mode" "$dst"
|
|
}
|
|
|
|
# --- 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)."
|
|
}
|
|
|
|
purge_obsolete_files() {
|
|
info "Analyse des fichiers obsolètes (Synchronisation avec le journal)..."
|
|
|
|
# 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
|
|
|
|
# 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 ---
|
|
|
|
main() {
|
|
require_root
|
|
install_deps
|
|
prepare_dirs
|
|
fetch_manifest
|
|
|
|
if ! validate_manifest > "${TMP_DIR}/manifest-valid.txt"; then
|
|
err "Le manifeste est invalide ou corrompu."
|
|
exit 1
|
|
fi
|
|
|
|
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
|
|
|
|
rm -rf "${TMP_DIR}"
|
|
echo "--------------------------------------------------"
|
|
ok "Opération terminée avec succès."
|
|
|
|
# --- 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 "$@" |