Systemd/timers
Timers are systemd unit files whose name ends in .timer that control .service files or events. Timers can be used as an alternative to cron
. Timers have built-in support for calendar-based events and monotonic time events, and can be run asynchronously.
Configuration
The following example timer runs a systemd unit every 5 minutes which invokes a bash script.
systemd.timers."hello-world" = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "5m";
OnUnitActiveSec = "5m";
Unit = "hello-world.service";
};
};
systemd.services."hello-world" = {
script = ''
set -eu
${pkgs.coreutils}/bin/echo "Hello World"
'';
serviceConfig = {
Type = "oneshot";
User = "root";
};
};
Alternatively here, avoid quotes when calling for the binary and its command options:
${pkgs.foo}/bin/foo command-options
This will yield the same result as running
foo command-options
in your terminal.
Using the systemd.services.<name>.startAt
shorthand
If you only want a service to execute at an interval and don't plan to configure the timer much more, you can use the systemd.services.<name>.startAt
option. This will have the underlying systemd module in nixpkgs create the timer for you, and set its OnCalendar
field. Note that the semantics for OnCalendar
are different to OnUnitActiveSec
.
This example shows the previous hello-world
service configured with startAt
, running every 5 minutes.
systemd.services."hello-world" = {
script = ''
set -eu
${pkgs.coreutils}/bin/echo "Hello World"
'';
serviceConfig = {
Type = "oneshot";
User = "root";
};
startAt = "*:0/5";
};
Running timer on a schedule
The following example starts once a day (at 12:00am). When activated, it triggers the service immediately if it missed the last start time (option Persistent=true), for example due to the system being powered off.
...
timerConfig = {
OnCalendar = "daily";
Persistent = true;
};
};
More examples can be found at the Arch Wiki and at the systemd.timer
manpage.
Usage
List active timers and their current state:
systemctl list-timers
Manually run a service once for testing purposes:
systemctl start hello-world