#!/bin/bash # Initialiser les tableaux ignored_machines=() ok_machines=() error_machines=() # Variables pour les codes de couleur ANSI RED='\033[0;31m' GREEN='\033[0;32m' NC='\033[0m' # No Color # Mise à jour des machines présentes dans .ssh/config avec choix d'ignorer certaines. # fonction run_ssh et run_scp avec timeout + options SSH_OPTS="-o ConnectTimeout=5 -o BatchMode=yes -o StrictHostKeyChecking=accept-new" SSH_TIMEOUT="5" run_ssh() { local machine="$1" local start_time=$(date +%s) shift if [ $# -eq 0 ]; then ssh "$machine" 'bash -s' < /dev/stdin else ssh "$machine" "$@" fi local end_time=$(date +%s) local duration=$(( end_time - start_time )) echo -e " ⏱️ Durée : ${duration}s" } extract_stats_block() { local label="$1" grep -A2 "^>>> $label" "$logfile" | grep -E '^[0-9]+ mis à jour' | tail -n1 } parse_summary_line() { awk ' { updated += $1 installed += $4 removed += $7 last_notup = $11 } END { print updated, installed, removed, (last_notup ? last_notup : 0) }' } run_scp() { local src="$1" local dest="$2" local machine="$3" timeout "$SSH_TIMEOUT" scp $SSH_OPTS "$src" "$machine:$dest" } update_with_apt() { local machine="$1" local uniqkey="$2" local start_time=$(date +%s) echo -e " - Mise à jour avec apt-get sur $machine \n" stats_tmp=$(mktemp) run_ssh "$machine" <<'EOF' | tee "$stats_tmp" export DEBIAN_FRONTEND=noninteractive echo ">>> clean" sudo apt-get -y clean echo ">>> update" sudo apt-get update echo ">>> check-upgrade" UPGRADABLE=$(apt-get -s upgrade | grep "^Inst" | wc -l) if [ "${UPGRADABLE:-0}" -gt 0 ] 2>/dev/null; then echo ">>> upgrade" sudo apt-get -y upgrade echo ">>> full-upgrade" sudo apt-get -y full-upgrade echo ">>> autoremove" sudo apt-get -y autoremove else echo ">>> Aucun paquet à mettre à jour" fi if [ -f /var/run/reboot-required ]; then echo ">>> REDÉMARRAGE NÉCESSAIRE" fi EOF local end_time=$(date +%s) local duration=$(( end_time - start_time )) log_capture=$(cat "$stats_tmp") local ssh_status=$? if [ "$ssh_status" -ne 0 ]; then echo -e "❌ Échec SSH ou erreur distante sur $machine (code $ssh_status)" else echo -e "✅ $machine : Terminé avec succès" fi echo # Récupération stats à partir des logs visibles en live # On extrait les chiffres comme dans le message de apt # Initialisation des compteurs updated=0 installed=0 removed=0 unchanged=0 # Extraire les lignes après chaque bloc line_upgrade=$(echo "$log_capture" | grep -A2 '^>>> upgrade' | grep -E '^[0-9]+ mis à jour' | tail -n1) line_fullup=$(echo "$log_capture" | grep -A2 '^>>> full-upgrade' | grep -E '^[0-9]+ mis à jour' | tail -n1) line_autorm=$(echo "$log_capture" | grep -A2 '^>>> autoremove' | grep -E '^[0-9]+ mis à jour' | tail -n1) # Ajouter les lignes ensemble line_all="$line_upgrade"$'\n'"$line_fullup"$'\n'"$line_autorm" read updated installed removed unchanged <<< $(echo "$line_all" | parse_summary_line) # Date/heure actuelle now=$(date '+%Y-%m-%d %H:%M:%S') # Fichier de stats stats_file="$HOME/.config/updateall-stats" mkdir -p "$(dirname "$stats_file")" # Ajouter l’en-tête si le fichier est vide if [ ! -s "$stats_file" ]; then echo "machine,date,duree,updated,installed,removed,unchanged,uniqkey" > "$stats_file" fi # Ajout ligne CSV echo "$machine,$now,$duration,$updated,$installed,$removed,$unchanged,$uniqkey" >> "$stats_file" } # Fonction pour mettre à jour avec dnf update_with_dnf() { echo -e " - Mise à jour avec dnf sur $1 \n" run_ssh "$1" 'sudo dnf check-update && sudo dnf upgrade -y' echo -e "\n" } # Déclaration d'une fonction pour récupérer les alias à partir du fichier ~/.ssh/config get_ssh_aliases() { # Parcours du fichier ~/.ssh/config et récupération du premier Host (excluant "*") awk 'tolower($1) == "host" && $2 != "*" && !seen[$2]++ {print $2}' ~/.ssh/config # Parcours des fichiers dans le dossier ~/.ssh/include et récupération du premier Host (excluant "*") for include_file in ~/.ssh/include/*; do awk 'tolower($1) == "host" && $2 != "*" && !seen[$2]++ {print $2}' "$include_file" done } check_keyinstall() { local machine="$1" local uniqkey="$2" local uniqkey_file="/etc/cedrix_updateall" echo -n " - Vérification d'une mise à jour déjà effectuée sur "$machine" : " if ! timeout 5 ssh "$machine" '[ -f "$uniqkey_file" ]'; then echo -e "${GREEN}mise à jour à faire.${NC}" return 0 fi if timeout 5 ssh "$machine" "grep -q '$uniqkey' $uniqkey_file"; then echo -e "${RED}mise à jour déjà faite.${NC}" return 1 fi timeout 5 ssh "$machine" "sudo rm "$uniqkey_file"" echo -e "${GREEN}mise à jour à faire et clé à modifier.${NC}" return 0 } create_installkey() { local machine="$1" local uniqkey="$2" local uniqkey_file="/etc/cedrix_updateall" echo -n " - Indiquer à $machine que le script est passé ... " # Si la clé unique n'est pas présente, la déposer dans le fichier echo "$uniqkey" | timeout 5 ssh "$machine" "sudo su -c \"cat > $uniqkey_file\"" result="$?" if [ $result -eq 0 ]; then echo -e "${GREEN}OK${NC}" else echo -e "${RED}une erreur est survenue. Désactivation des prochaines mise à jour.${NC}" fi return } # Fonction pour récupérer la valeur de /etc/os-release get_os_release() { ssh "$1" 'grep "^PRETTY_NAME=" /etc/os-release' | cut -d'=' -f2 | tr -d \" } update_machine () { local machine="$1" # recupérer le nom de l'OS os_name=$(get_os_release "$machine") echo -e " - Système d'exploitation : ${GREEN}$os_name${NC}" echo -n " - Détection du gestionnaire de mise à jour ... " if timeout 5 ssh "$machine" which apt > /dev/null 2>&1; then echo -e "${GREEN}apt${NC}" update_with_apt "$machine" "$uniqkey" elif timeout 5 ssh "$machine" which dnf > /dev/null 2>&1; then echo -e "${GREEN}dnf${NC}" update_with_dnf "$machine" else echo " ${RED} non détecté${NC}" fi } confirm_update() { local machine="$1" read -p " - Executer la mise à jour pour $machine ? (o/n) " choice if [ "$choice" = "o" ]; then echo "$machine 1" >> ~/.config/updateall-hosts else echo "$machine 0" >> ~/.config/updateall-hosts continue fi } check_host() { local machine="$1" echo -n " - Check host " # Vérifier la résolution du nom d'hôte if ssh "$machine" hostname > /dev/null 2>&1; then echo -e "... ${GREEN}OK${NC}" return 1 else echo -e "... ${RED}KO${NC}" return 0 fi } run_custom_script() { local machine="$1" local custom_script="$HOME/.config/updateall.d/$machine" if [ -f "$custom_script" ]; then echo -e " - Exécution du script spécifique pour ${GREEN}$machine${NC}" # Copier le script sur la machine et l'exécuter run_scp "$custom_script" "/tmp/updateall_custom.sh" "$machine" if [ $? -eq 0 ]; then echo " - Script copié, exécution en cours..." run_ssh "$machine" ' chmod +x /tmp/updateall_custom.sh sudo /tmp/updateall_custom.sh status=$? sudo rm -f /tmp/updateall_custom.sh exit $status ' else echo -e "${RED} - Échec du transfert du script personnalisé${NC}" fi else echo " - Aucun script spécifique pour $machine." fi } # Générer une clé unique uniqkey=$(uuidgen) echo "Clé d'installation : $uniqkey" # Récupérer les alias SSH machines=($(get_ssh_aliases)) echo -e "\n--- Démarrage du traitement ---\n" # Parcourir la liste des machines total=${#machines[@]} current=0 for machine in "${machines[@]}"; do # Vérification si le nom de machine est présent dans le fichier .config/updateall-hosts echo -e "\n" ((current++)) echo -ne ">> $machine ($current/$total)\n" while read host status; do # ignorer commentaires et lignes vides [[ -z "$host" || "$host" =~ ^# ]] && continue if [ "$machine" = "$host" ]; then if [ "$status" = "1" ]; then echo -e "${GREEN}connue${NC}" check_host "$machine" machine_online="$?" if [ "$machine_online" -eq 1 ]; then check_keyinstall "$machine" "$uniqkey" keyinstall_present="$?" if [ "$keyinstall_present" -eq 0 ]; then update_machine "$machine" create_installkey "$machine" "$uniqkey" ok_machines+=("$machine") fi else error_machines+=("$machine") fi else echo -e "${RED}ignorée${NC}" ignored_machines+=("$machine") fi matched=1 break fi done < ~/.config/updateall-hosts if [ "$matched" != "1" ]; then check_host "$machine" machine_online="$?" if [ "$machine_online" -eq 1 ]; then echo -e "${RED}vue pour la 1re fois${NC}" confirm_update "$machine" update_machine "$machine" run_custom_script "$machine" create_installkey "$machine" "$uniqkey" ok_machines+=("$machine") else echo -e "${RED}non accessible${NC}" error_machines+=("$machine") fi fi done echo -e "\n--- Résumé des machines ---\n" # Afficher les machines ignorées echo -e "${RED}Machines ignorées :${NC}" for machine in "${ignored_machines[@]}"; do echo " - $machine" done echo "" # Afficher les machines en erreur echo -e "${RED}Machines en erreur :${NC}" for machine in "${error_machines[@]}"; do echo " - $machine" done echo "" # Afficher les machines ok echo -e "${GREEN}Machines mises à jour avec succès :${NC}" for machine in "${ok_machines[@]}"; do echo " - $machine" done echo ""