46

I am attempting to create and install on Bionic a custom pair of systemd timer & service units for running a command periodically. I know that the files should be placed in /etc/systemd/system and then I should run systemctl daemon-reload, but I'm not clear on whether I need to enable or start anything in order for the timer to be fully installed and "running," and the few articles I can find that address this point all give different information.

My .timer file is:

[Unit]
Description=Run custom command periodically

[Timer]
Unit=my-custom-command.service
OnCalendar=*-*-* 0/8:00:00

[Install]
WantedBy=timers.target

My .service file is:

[Unit]
Description=Run a custom command
OnFailure=mail-systemd-failure@%n.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/custom-command
User=dedicated-user
Group=dedicated-user

The conflicting articles I've read are:

  • This article says to run:

    systemctl daemon-reload
    systemctl enable $NAME.timer
    systemctl start $NAME
    

    As I understand it, the latter command is the same as systemctl start $NAME.service, which I would expect to immediately run the command defined by the service, which is not what I want to do.

  • This gist says to just run:

    systemctl daemon-reload
    systemctl start $NAME.timer
    
  • This article says to run:

    systemctl enable $NAME.timer
    systemctl start $NAME.timer
    

So do I enable and/or start the timer (or its service?), and what exactly is the difference between the two? Do the commands I need to run change depending on whether the unit files are newly installed or being reloaded after an edit?

0

1 Answer 1

83

To run a unit at specified times or intervals you need two units:

  • a service unit that defines what to run
  • a timer unit that defines when to run the service unit

By convention, the timer unit starts another unit with the same name, i.e. foo.timer starts foo.service. You can override this by defining the Unit=other.service attribute in the timer unit (like you did).

If both unit files are created and put in /etc/systemd/system you need to make systemd aware of them by issuing

systemctl daemon-reload

This makes systemd reload all unit files and re-consider their dependencies because systemd caches these files somehow. So whenever you change a unit file, this command is required.

After that you need to enable the timer unit:

systemctl enable foo.timer

This commands simply enables auto-start at boot time (but doesn't start the unit yet). Do not enable the service unit because that would mean to start the service at boot time (independent of any timer settings).

Now the next time you boot, the timer will be engaged. To start it immediately (without booting) you would run

systemctl start foo.timer

From now on, the timer unit will start the service unit whenever the time comes. You can combine enabling and starting with

systemctl enable --now foo.timer

You can (and should) leave the service unit alone, i.e. neither enable nor start it. This is now handled by the timer unit.

To see the current status of both timer and service, issue

systemctl status foo.timer foo.service

To summarize

  • systemctl enable/disable controls the behaviour when booting
  • systemctl start/stop controls the behaviour right now
  • enable does not imply start (neither does disable imply stop). This can be overriden with the --now switch.
  • only enable and start the timer unit, not the service unit
  • issue systemctl daemon-reload whenever you edit the unit files

Further reading:

1
  • 6
    --now I understand.
    – Cymatical
    Mar 18, 2021 at 20:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .