[systemd-devel] timers always run when time changes

Lennart Poettering lennart at poettering.net
Mon May 18 10:16:23 PDT 2015

On Fri, 01.05.15 09:35, Likang Wang (laborish at gmail.com) wrote:

> Hi all,
> I hava a timer with the fellowing setting:
> # cat /lib/systemd/system/updateimage.timer
> [Unit]
> Description=Update image
> DefaultDependencies=false
> [Timer]
> OnCalendar=*-*-* 02:00:00
> Persistent=false
> [Install]
> WantedBy=multi-user.target
> And I want the timer call the same-name service only on 02:00:00 daily.
> The entire system is running on an embedded box, and the system time will
> be set to 2008-01-01 00:00:00 after every reboot. My app running on the box
> will get the real time from my server and update time on the box after
> every booting.(I could not use NTP or systemd-timesyncd for some other
> reason)
> Here is my problem.
> When my app set the system time to real time, systemd will wake up the
> updateimage.timer and run the updateimage.service no matter what time it it
> now.The log looks like this:
> Jan  1 08:14:00 systemd[1]: xxxxxx.service: cgroup is empty
> Apr 30 21:04:00 systemd[1]: Time has been changed
> Apr 30 21:04:00 systemd[1]: Set up TFD_TIMER_CANCEL_ON_SET timerfd.
> Apr 30 21:04:00 systemd[1]: Timer elapsed on updateimage.timer
> Apr 30 21:04:00 systemd[1]: Trying to enqueue job
> updateimage.service/start/replace
> Apr 30 21:04:00 systemd[1]: Installed new job updateimage.service/start as
> 9269
> What I want is the timer and the same-name service only run exactly on
> 02:00:00 daily, but not when time changes. What should I do?

Well, the way this works is that when the timer unit is started
systemd determines the next time the unit shall elapse. Given that
your clock is initialized to 2008-01-01 00:00:00 this means it will
calculated 2008-01-02 02:00:00. Then, when you make the clock jump,
and it becomes 2015-04-30 21:04:00 systemd notes that the calculated
elapsing time is now already in the past and immediately dispatch the
timer unit.

In most cases this is arguably what you want since it gives you the
guarantee that your service is always run less time ago than the
interval you specified -- on the wallclock.

Now I can see that in you case this behaviour might not be
advisable. Two suggestions:

- consider using "systemd-timesyncd" for time synchronization. It
  implements sNTP and will sync the last known time to disk every time
  it gets an sNTP sync or the system is shut down. At boot it uses
  that time to reinitialize the clock, as early as possible, before
  NTP is done. THis will give you monotonic time which should solve
  your probelm.

- Introduce some flag file to conditionalize your service with
  ConditionPathExists= or so, so that it is only started when the
  clock was set at least once... Each time you sync the clock, create
  that file. if it is missing you hence know that the clock is not
  ready for syncing on...


Lennart Poettering, Red Hat

More information about the systemd-devel mailing list