
Dans cet article, je présente un script simple (mais très efficace) pour automatiser les mises à jour des machines virtuelles sur Proxmox VE. Le script peut :
- créer une sauvegarde de la VM (optionnel),
- démarrer la VM si elle était arrêtée au départ,
- effectuer une mise à niveau complète via apt et redémarrer la VM,
- lancer des tests réseau avant et après la mise à jour,
- restaurer automatiquement depuis la sauvegarde en cas de problème (optionnel),
- éteindre la VM à la fin si elle était initialement arrêtée.
Où télécharger le script
Vous pouvez télécharger le script directement depuis mon site :
soban.pl/bash/upgrade_proxmox_qm.sh
Dossiers requis
Avant de lancer l’automatisation, créez deux dossiers : un pour les scripts et un pour les logs :
|
1 |
mkdir -p /root/automate_scripts /root/logs |
Installer le script
Téléchargez le script dans /root/automate_scripts/ et rendez-le exécutable :
|
1 2 3 |
cd /root/automate_scripts curl -fsSL -o upgrade_proxmox_qm.sh "https://soban.pl/bash/upgrade_proxmox_qm.sh" chmod +x /root/automate_scripts/upgrade_proxmox_qm.sh |
Comment ça marche (version courte)
- D’abord, une sauvegarde est créée (vzdump snapshot + zstd) si l’option est activée.
- Si la VM était en état stopped, le script la démarre et attend WAIT_TIME secondes.
- Ensuite, le script exécute des tests réseau AVANT la mise à jour :
- Le script exécute apt update/upgrade/dist-upgrade/autoremove/clean puis redémarre la VM (reboot).
- Après le redémarrage, il attend à nouveau (WAIT_TIME) et relance les tests APRÈS la mise à jour.
- Si les tests échouent et qu’une sauvegarde est disponible, la VM est restaurée automatiquement via qmrestore.
- Enfin, la VM est arrêtée si elle était initialement arrêtée.
Lancer le script manuellement
Le script attend exactement deux arguments :
VMID– l’ID de la VM dans ProxmoxTIME_SEC– le temps d’attente après démarrage/redémarrage (en secondes)
|
1 |
/root/automate_scripts/upgrade_proxmox_qm.sh 901 500 |
Astuce : adaptez WAIT_TIME au temps réel de démarrage de la VM et à la durée de la mise à jour. En pratique, 300 à 1000 secondes fonctionnent très bien selon la VM.
Script complet (référence)
Ci-dessous, le script complet (code et commentaires restent en anglais) :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
#!/bin/bash WAIT_TIME=$2 # wait time for VM start/restart (in seconds) DO_BACKUP="y" # 'y' - create backup, 'n' - skip backup DO_UPDATE="y" # 'y' - run system update, 'n' - skip update echo "---------------START---------------" date echo "-----------------------------------" # Argument check if [ "$#" -ne 2 ]; then echo "Usage: $0 <VMID> <TIME_SEC>" exit 1 fi VMID="$1" TARGET_HOSTNAME=$(/usr/sbin/qm list | grep -w "$VMID" | awk '{print $2}') VM_STATUS=$(/usr/sbin/qm status "$VMID" | awk '{print $2}') HOST_MACHINE=$(hostname) WAS_STOPPED=0 if [ "$VM_STATUS" = "stopped" ]; then WAS_STOPPED=1 else WAS_STOPPED=0 fi # Create backup if DO_BACKUP is set to 'y' backup_result="Backup not attempted" if [ "$DO_BACKUP" = "y" ]; then echo "Creating backup for VM $VMID..." BACKUP_OUTPUT=$(/usr/bin/vzdump "$VMID" --storage local --mode snapshot --compress zstd) BACKUP_FILE=$(echo "$BACKUP_OUTPUT" | grep -oP 'vzdump-qemu-[^\s]+' | tr -d "'") if [ -z "$BACKUP_FILE" ]; then echo "Backup failed: No backup file created." backup_result="Backup created: NOK" exit 1 else echo "Backup created successfully: $BACKUP_FILE" backup_result="Backup created: OK" fi else echo "Backup not attempted (backup is disabled)." fi # Start VM if it was originally stopped if [ "$WAS_STOPPED" -eq 1 ]; then echo "Starting VM $VMID for update..." /usr/sbin/qm start "$VMID" echo "Waiting $WAIT_TIME seconds for VM to start..." sleep "$WAIT_TIME" fi # Test functions perform_ping_test() { source="$1" target="$2" if ssh root@"$source" "ping -c 3 -W 2 $target" >/dev/null 2>&1; then echo "Ping from $source to $target: OK" return 0 else echo "Ping from $source to $target: NOK" return 1 fi } test_curl() { source="$1" target="$2" if ssh root@"$source" "curl -s --head --connect-timeout 5 $target" >/dev/null 2>&1; then echo "Curl from $source to $target: OK" return 0 else echo "Curl from $source to $target: NOK" return 1 fi } perform_local_ping_test() { source="$1" target="$2" if ping -c 3 -W 2 "$target" >/dev/null 2>&1; then echo "Ping from $source to $target: OK" return 0 else echo "Ping from $source to $target: NOK" return 1 fi } DEFAULT_GW=$(/sbin/ip route | grep default | awk '{print $3}') perform_tests() { status=0 perform_local_ping_test "$HOST_MACHINE" "$TARGET_HOSTNAME" || status=1 perform_ping_test "$TARGET_HOSTNAME" "8.8.8.8" || status=1 perform_ping_test "$TARGET_HOSTNAME" "$DEFAULT_GW" || status=1 test_curl "$TARGET_HOSTNAME" "http://google.com" || status=1 return ${status:-0} } # General tests before update echo "--- General tests BEFORE update ---" if perform_tests; then echo "All network tests before update: OK" echo "$backup_result" if [ "$backup_result" == "Backup created: OK" ] || [ "$backup_result" == "Backup not attempted" ]; then echo "BEFORE status: OK" else echo "BEFORE status: NOK" fi else echo "Some network tests before update: NOK" echo "$backup_result" echo "BEFORE status: NOK" [ "$WAS_STOPPED" -eq 1 ] && /usr/sbin/qm shutdown "$VMID" exit 1 fi echo "-----------------------------------" # System update and reboot update_result="Upgrade system: NOK" if [ "$DO_UPDATE" = "y" ]; then echo "--- Updating VM $VMID ---" if ssh root@"$TARGET_HOSTNAME" "/usr/bin/apt update && \ /usr/bin/apt upgrade -y && \ /usr/bin/apt dist-upgrade -y && \ /usr/bin/apt autoremove -y && \ /usr/bin/apt autoclean && \ /usr/bin/apt clean && \ /usr/bin/apt --purge autoremove && \ /sbin/reboot"; then echo "---END Updating VM $VMID ---" echo "Upgrade system: OK" update_result="Upgrade system: OK" else echo "Upgrade system: NOK" update_result="Upgrade system: NOK" [ "$WAS_STOPPED" -eq 1 ] && /usr/sbin/qm shutdown "$VMID" echo "Update failed. Exiting." exit 1 fi fi # Wait for VM reboot if update was performed if [ "$DO_UPDATE" = "y" ]; then echo "Waiting $WAIT_TIME seconds for VM to reboot..." sleep "$WAIT_TIME" fi # Tests after reboot if update was performed if [ "$DO_UPDATE" = "y" ]; then echo "--- Network tests AFTER update ---" if perform_tests; then echo "All network tests after update: OK" echo "$update_result" echo "AFTER status: OK" else echo "Some network tests after update: NOK" echo "$update_result" echo "Attempting to restore from backup..." if [ "$DO_BACKUP" = "y" ]; then /usr/sbin/qm stop "$VMID" /usr/sbin/qmrestore "/var/lib/vz/dump/$BACKUP_FILE" "$VMID" --force if [ "$WAS_STOPPED" -eq 1 ]; then /usr/sbin/qm shutdown "$VMID" fi echo "Restore attempt finished. Please check VM status." echo "AFTER status: NOK" else echo "No backup available for restoration. The VM might not function properly after failed update." echo "AFTER status: NOK" fi fi echo "-----------------------------------" fi # Shut down VM if it was originally stopped if [ "$WAS_STOPPED" -eq 1 ]; then echo "Shutting down VM $VMID (originally stopped)." /usr/sbin/qm shutdown "$VMID" fi echo "---------------END---------------" date echo "-----------------------------------" |
Cron (planning hebdomadaire + logs séparés par VM)
Voici un exemple de crontab : une VM différente est mise à jour chaque jour de la semaine, et les logs sont enregistrés dans des fichiers séparés sous /root/logs/.
Modifier le crontab root :
|
1 |
crontab -e |
Collez les règles ci-dessous (les commentaires restent en anglais) :
|
1 2 3 4 |
15 0 * * 1 /root/automate_scripts/upgrade_proxmox_qm.sh 901 500 > /root/logs/kali.log 2>&1 # Monday: upgrade Kali Linux (VMID 901) 15 0 * * 2 /root/automate_scripts/upgrade_proxmox_qm.sh 903 500 > /root/logs/proxmox-test-01.log 2>&1 # Tuesday: upgrade proxmox-test-01 (VMID 903) 15 0 * * 3 /root/automate_scripts/upgrade_proxmox_qm.sh 904 500 > /root/logs/ubuntu-lte.log 2>&1 # Wednesday: upgrade ubuntu-lte (VMID 904) 15 0 * * 4 /root/automate_scripts/upgrade_proxmox_qm.sh 905 1000 > /root/logs/backup-machine.log 2>&1 # Thursday: upgrade backup-machine (VMID 905) |
Vérifications rapides / Dépannage
- Assurez-vous que root peut se connecter en SSH depuis l’hôte Proxmox vers la VM (le script utilise
ssh root@<vm-hostname>). - Vérifiez que DNS (ou
/etc/hosts) résout correctement le hostname de la VM sur l’hôte Proxmox. - Si apt demande des confirmations, configurez des mises à niveau non interactives ou bloquez les paquets problématiques.
Voilà ! Déposez le script dans /root/automate_scripts/, envoyez les journaux dans /root/logs/, et la maintenance hebdomadaire de votre machine virtuelle devient quasiment automatique.