4

While it's relatively straightforward to setup systemd to start a service at a particular time, how can I also make it stop at a different time?

The idea would be to run a service overnight only, and stop it in the morning.

Artur Meinild
  • 26,018
  • 1
    There is some reason for avoiding the use of crontab? – Alessandro Carini Aug 04 '23 at 11:43
  • @AlessandroCarini there could be several reasons. systemd timers have a more flexible configuration than crontab. And this is a perfectly valid question about systemd, so no reason to make it about crontab. – Artur Meinild Aug 04 '23 at 11:49

1 Answers1

3

You are correct, that a systemd timer is designed in a way so that it starts a service at a specific time. So to make it stop a service, it's necessary to make a workaround.

Luckily, there are several ways to achieve this.

Option 1: Make Service A conflict with Service B

The first option is to create a oneshot Service B that is in conflict with Service A. The advantage of this method is that it relies solely on systemd unit files, but the disadvantage is that you have to modify Service A (or create drop-in configuration).

First, you need to modify the configuration of Service A, so it conflicts with Service B:

Add this the configuration of A.service:

[Unit]
Conflicts=B.service
...

Then create a B.service that does nothing:

[Unit]
Description=B service description

[Service] Type=oneshot ExecStart=/bin/echo ''

This method is taken from this Q&A.

Option 2: Make Service B simply stop Service A

Another option is to create a oneshot Service B that simply runs the command to stop Service A. The advantage of this method is that you don't have to modify Service A, but the disadvantage is that it relies on running systemctl and not solely on systemd unit files.

For this method, you only need to create a B.service, but this time it will run a command:

[Unit]
Description=B service description

[Service] Type=oneshot ExecStart=/usr/bin/systemctl stop A.service

For both options, you then create a different timer for each of those services. Timer A will now start Service A, and Timer B will later start Service B - effectively stopping Service A.

See this Q&A for more information about setting up systemd services and timers.

Artur Meinild
  • 26,018
  • 1
    For completeness: RuntimeMaxSec= might be set although will report the service as failed after termination, but that can only be cosmetic in most cases ... And if that service is used to run a script, then some logic can be implemented within the script to end both as well. – Raffa Aug 04 '23 at 08:12
  • 1
    Thanks a lot, I've set this up and it looks like it should work. Meanwhile I've also put a feature request with systemd to simplify this. – Vadim Peretokin Aug 05 '23 at 07:25