Skip to content

Arrêt automatique Proxmox (VM, LXC et hôte)

pve01 s’allume via Wake-on-LAN quand j’en ai besoin. Le soir, je veux l’éteindre sans avoir à me connecter à la main — mais surtout sans couper le courant pendant qu’une VM écrit sur disque ou qu’un LXC termine une opération. Un hard power-off « pour aller plus vite » finit toujours par coûter plus cher en restauration ou en doute sur l’intégrité des données. D’où ce guide : un script qui demande un arrêt gracieux aux VM et aux conteneurs, attend, force ce qui reste bloqué, puis coupe l’hôte ; un cron le déclenche à heure fixe (22h10 chez moi).

Le script vit en /usr/local/bin/full_shutdown.sh. Il parcourt d’abord les VM (qm) et les LXC (pct), lance un shutdown avec timeout en parallèle, patiente quatre-vingt-dix secondes pour laisser les systèmes d’invités finir proprement, puis repasse en stop forcé sur ce qui tourne encore. Seulement ensuite il appelle shutdown -h now sur l’hôte Proxmox. Ce n’est pas élégant, mais c’est prévisible — et c’est ce que je veux à 22h quand je ne suis plus devant l’écran.

#!/bin/bash
# Arrêt complet Proxmox : VM + LXC + hôte
# Arrêt propre avec délai, puis forcé si besoin
echo "=== [$(date)] Début de la séquence d'arrêt complet ==="
echo "--- Arrêt des machines virtuelles ---"
for vmid in $(qm list | awk 'NR>1 {print $1}'); do
echo "Arrêt VM $vmid ..."
qm shutdown "$vmid" --timeout 60 &
done
echo "--- Arrêt des conteneurs LXC ---"
for ctid in $(pct list | awk 'NR>1 {print $1}'); do
echo "Arrêt LXC $ctid ..."
pct shutdown "$ctid" --timeout 60 &
done
echo "--- Pause de 90 secondes pour arrêt propre ---"
sleep 90
echo "--- Arrêt forcé des VM restantes ---"
for vmid in $(qm list | awk 'NR>1 {print $1}'); do
status=$(qm status "$vmid" | awk '{print $2}')
if [ "$status" = "running" ]; then
echo "Arrêt forcé VM $vmid"
qm stop "$vmid"
fi
done
echo "--- Arrêt forcé des LXC restants ---"
for ctid in $(pct list | awk 'NR>1 {print $1}'); do
status=$(pct status "$ctid" | awk '{print $2}')
if [ "$status" = "running" ]; then
echo "Arrêt forcé LXC $ctid"
pct stop "$ctid"
fi
done
echo "=== Toutes les VM et LXC sont arrêtées ==="
echo "--- Extinction du serveur ---"
shutdown -h now

On le rend exécutable, puis on le teste une fois à la main en acceptant que la machine s’éteigne pour de bon. Ce n’est qu’après ce test que je fais confiance au cron : un script jamais exécuté « parce que ça a l’air bon » est exactement le genre de surprise du dimanche soir.

Terminal window
chmod +x /usr/local/bin/full_shutdown.sh
/usr/local/bin/full_shutdown.sh

Sous root, crontab -e, une ligne suffit pour lancer le script tous les soirs à 22h10 :

10 22 * * * /usr/local/bin/full_shutdown.sh

Je vérifie que le service cron est actif et que la crontab contient bien la ligne (systemctl enable --now cron, crontab -l). L’heure se déplace selon l’usage — l’important, c’est le couple avec le WoL : allumer pve01 quand le lab k3s sert, l’éteindre proprement quand il ne sert plus. Sur un cluster qu’on laisse 24h/24, ce script n’a pas d’intérêt ; sur un nœud on-demand, c’est ce qui rend le schéma tenable sans y penser chaque soir.