Files
scripts-bash/local/bin/updateall.sh
2025-08-17 13:02:48 +02:00

416 lines
10 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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 len-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 ""