WSL2 Clock is out of sync with Windows

Viewed 21333

WSL2 clock goes out of sync after resuming from sleep/hibernate. illustration showing Windows clock and WSL clock out of sync

A workaround was shared on GitHub sudo hwclock -s to resync clock in WSL, but you have to do this every time you resume from sleep/hibernate.

9 Answers

In case anyone finds this via search and doesn't notice that there is actually a solution listed in the question, you can fix WSL clock drift via.

sudo hwclock -s

If you just need to do it occasionally, this is a fine solution. If you need to do it more frequently, consider @piouson's solution

sudo hwclock -s gets you kind of there, but for some reason doesn't get the exact time - I often find it's a minute or so in the future!

sudo ntpdate pool.ntp.org should get you the correct time.

But this is all because of a bug in the Linux kernel which should be included in a Windows update at some point...

There are a number of hacks referenced in the the GitHub issue which can work around this, mostly, but not always, in my experience...

UPDATE: The fix is now in! In the Windows Insiders build, at least: https://devblogs.microsoft.com/commandline/servicing-the-windows-subsystem-for-linux-wsl-2-linux-kernel/

UPDATE: as mentioned by drkvogel, the Clock Sync fix was released in WSL2 kernel version 5.10.16.3


OBSOLETE

At time of writing, this GitHub Issue was open for the bug.

The workaround I chose for my situation (single distro in WSL2) is to use Windows Task Scheduler to run hwclock in WSL whenever Windows resyncs hardware clock.

Windows: Open PowerShell as Administrator

schtasks /create /tn WSLClockSync /tr "wsl.exe sudo hwclock -s" /sc onevent /ec system /mo "*[System[Provider[@Name='Microsoft-Windows-Kernel-General'] and (EventID=1)]]"
Set-ScheduledTask WSLClockSync -Settings (New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries)

WSL2: Run sudo visudo and add hwclock to sudoers to skip password prompt

# bottom of my file looks like this
...
...
#includedir /etc/sudoers.d
<username> ALL=(ALL) NOPASSWD:/usr/sbin/hwclock, /usr/bin/apt update, /usr/bin/apt upgrade

Results

illustration showing Windows clock and WSL clock in sync

See image for how to get Event XPath from Windows Event filtering. Use as provided to let task scheduler auto-display scheduled triggers.

illustration showing scheduled task created

just restart wsl, it works fine for me

wsl --shutdown

then

wsl

in PowerShell

Necro'ing this: As of May 2022, this issue persists to a degree.

There are two components.

First, Windows time sync needs to be decent to start with. It's not, out of the box, on machines that aren't domain-joined.

  • Change w32time to start automatically. In Administrator cmd, but not PowerShell, sc triggerinfo w32time start/networkon stop/networkoff. Verify with sc qtriggerinfo w32time. To get into cmd that way, you can start Admin PowerShell and then just type cmd.

  • Make a few changes in regedit.

    • In Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w32time\Config, set MaxPollInterval to hex c, decimal 12.
    • Check Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w32time\Parameters\NtpServer. If it ends in 0x9 you are done. If it ends in 0x1 you need to adjust SpecialPollInterval in Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w32time\TimeProviders\NtpClient to read 3600
  • Reboot, then from Powershell run w32tm /query /status /verbose to verify that w32time service did start. If it didn't, check triggers again. If all else fails, set it to Automatic Delayed startup

Second, WSL2 needs to actually stay in sync. MS will likely release another kernel fix. In the meantime a scheduled task can bring it back into sync periodically: schtasks /Create /TN WSL2TimeSync /TR "wsl -u root hwclock -s" /SC ONEVENT /EC System /MO "*[System[Provider[@Name='Microsoft-Windows-Kernel-Power'] and (EventID=107 or EventID=507) or Provider[@Name='Microsoft-Windows-Kernel-General'] and (EventID=1)]]" /F

You can manually update the WSL2 kernel to 5.10.16 by following the method in this comment: #5650 (comment). I have fixed the issue by this method.

Use cron to schedule sudo hwclock -s

As others said before sudo hwclock -s syncs the clock,
but you will need to do this after every sleep/hibernate. Solution is to add an hourly cron task to sync the clock.

Open crontab with sudo (must open with sudo since the command uses sudo):

sudo crontab -e 

and add this code with a new line after the task (it's a cron requirement):

PATH=/sbin:/bin:/usr/bin
@hourly hwclock -s

You must either set PATH since root-cron do not has it or use absolute paths e.g. /usr/sbin/hwclock.

cron troubleshooting:

  • To verify cron is working you may add a dummy task (don't forget to add a new line):
    * * * * * date > /tmp/log.txt
  • If no file is created, verify cron is working: pgrep cron.
    If no PID shows, start cron with: sudo service cron start.
  • To learn cron timing method: cron timing generator

I've added this to Windows Task Scheduler, set to run every 12 hours:

wsl.exe -d ubuntu -u root -- ntpdate time.windows.com

To install ntpdate:

sudo apt install ntpdate

This GitHub Issue was closed

You can also run the below command in Powershell Terminal so sync it.

wsl.exe sudo hwclock -s

Related