I have a few Windows VMs running on Proxmox PVE, i need only from time to time. In the meantime, i hibernate them. After waking them up, they have the time from when I hibernated them and it’s not updated. I have to restart the windows time service or force a sync to get the correct time. Guest tools are installed and the QEMU agent is enabled. I found no option in the Proxmox PVE to sync time after hibernation, but this workaround with a hook script works for me:
- Create a hook script on the Proxmox host, for example at
/var/lib/vz/snippets/synctime.sh:
#!/bin/bash
# qm set <id> --hookscript local:snippets/synctime.sh
# Shutdown VM and then start it again to apply the hook script
# Test manually by running the script with the vmid and phase as arguments, for example:
# ./synctime.sh <vmid> post-start
# First argument is the vmid
vmid="$1"
# Second argument is the phase
phase="$2"
# Check if the two arguments are provided when testing the script
if [[ -z "$vmid" || -z "$phase" ]]; then
echo "Usage: $0 <vmid> <phase>"
echo "Example: $0 100 post-start"
exit 1
fi
echo "Running hook script for VM ID $vmid during phase $phase"
if [[ "$phase" == "post-start" ]]; then
# waiting for vm guest service to start
started="false"
loopstart=$EPOCHSECONDS
while [[ "$started" == "false" ]]; do
qm guest cmd $vmid ping && started="true"
if [[ "$started" == "false" ]]; then
sleep 2
fi
if (( EPOCHSECONDS-loopstart > 60 )); then
echo "timeout for vm guest service start"
break
fi
done
# sync VM time after resume or start
if [[ "$started" == "true" ]]; then
time=$(date +%s%N)
socket=/var/run/qemu-server/$vmid.qga
cmd="{\"execute\":\"guest-set-time\", \"arguments\":{\"time\":$time}}"
echo "$cmd" | socat - UNIX-CONNECT:"$socket"
echo "Time synchronization for VM ID $vmid completed."
else
echo "vm guest service not running"
exit 1
fi
fi
- Make the script executable:
chmod +x /var/lib/vz/snippets/synctime.sh
- Test the script to ensure it works correctly. Run
./synctime.sh <vmid> post-startand replace<vmid>with the ID of your VM. You should see output indicating that the time synchronization for the specified VM ID has been completed.
root@pve: ./synctime.sh 101 post-start
Running hook script for VM ID 101 during phase post-start
Time synchronization for VM ID 101 completed.
- Enable the hook script for your VM. Replace
101with your VM ID:
qm set 101 --hookscript local:snippets/synctime.sh
- Shutdown and Start the VM to apply the changes in the VM configuration.
- Now, every time you start the VM, the hook script will run and synchronize the time after hibernation. In the Task "VM x - Resume" you should see the output from the hook script indicating that the time synchronization has been completed:
Running hook script for VM ID 101 during phase pre-start
Resuming suspended VM
[...]]
Resumed VM, removing state
Running hook script for VM ID 101 during phase post-start
Time synchronization for VM ID 101 completed.
TASK OK
You can also check the log from the console with journalctl -fu qmeventd to see the output from the hook script when the VM starts.