0

Say I want a a program to be active between 12:00h and 13:00h on a desktop machine (i.e. if PC is on at either time cannot be guaranteed). I'll assume I can use systemd units for this.

Starting service A with a timer and accounting for poweroff times is simple:

A.timer

[Timer]
Unit=A
OnCalendar=*-*-* 12:00:00
Persistent=true

Stopping A could be done with a conflicting service as suggested earlier

A.service (with conflict):

#add conflict to A.service
[Unit]
Description=This is A.service
Conflicts=killA.service
#make sure killA considers A to be active
RemainAfterExit=yes

killA.service:

 [Unit]
 Description=kills A
 [Service]
 Type=oneshot
 ExecStart=/bin/true
 #kill only if A is running:
 Requires=A.service

killA.timer

[Timer]
Unit=killA
OnCalendar=*-*-* 13:00:00
Persistent=true

Now there are several possible scenarios:

  • Powered on from 11h-14h: start and stop as expected
  • Powered on from 11h to 12:30h: start as expected but never stopped -> what will happen at next poweron?

    • at 12:45: will A start? (last start less than 24h ago)
    • at 14h: killA should not run as A should not be active
    • at 12:15 next day? (last start less than 24 h ago, but killA start was missed)
    • at 12:45 next day? (last start >24h ago, but killA <24h ago. Will it be stopped by killA?)
  • Powered on from 12:30 to 14h: start and stop as expected (due to persistence in A.timer)

  • powered on at 14h: A starts due to persistence. Will killA deactivate it immediately due to dependency? Can starting A be avoided in the first place?

In short:

How to use systemd timers to make sure a service is active in a given time interval and inactive outside the time interval independently of shutdowns/boots ?


Hands-on use-case example: allow ssh-access only at working hours.

PS: Maybe I just don't get systemd timers very well, yet?

1

I had the same requirements.

I can confirm that two timers catching up at boot result in a race condition, with a random outcome.

And what about a scenario where the system reboots more than once between 12 and 13. Persistent may not be of any help in that case.

My conclusion (but I would love to be proven wrong) is that systemd is simply not made for this use case.

My work around is to use the above configuration, without the Persistent flags. Then I create a new idle service dedicated to handle state after startup. This service compares the current time with the current target service state, and starts/stops the service if they do not match. Note that the start/stop times need to be duplicated in the timers and in the 'startup manager' service script, which is not ideal.

That's the only reliable way I found to ensure my service is running during the selected time period, regardless of the various reboots.

  • The idle-service is starting a shell script, then? In pseudo-code if [ <time in active interval> && <service inactive> ] ; then <start service> ; elif [ <time in incative interval> && <service active> ] ; then <stop service> ; fi or do you manage this by systemd-logics? – Fiximan Nov 22 '19 at 13:31
  • 1
    Yes, that's what I did. – Gilles Debunne Nov 23 '19 at 16:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.