systemd

Table of Contents

1. Backup files on a schedule with timer units

A timer unit is used for timer-based activation of a matching service unit, e.g. foo.timer will activate foo.service.

User units are stored in ~/.config/systemd/user/.

For example to backup the fish shell history file with rsync, create this timer unit file backup-fish-history.timer.

# ~/.config/systemd/user/backup-fish-history.timer - systemd.timer(5)
[Unit]
Description=Backup fish history every sunday at 01:00

[Timer]
OnCalendar=Sun 01:00
RandomizedDelaySec=5minutes
Persistent=true
Unit=backup-fish-history.service

[Install]
WantedBy=timers.target

And its associated timer unit service unit file (%h is a specifier that expands to the user home directory).

# ~/.config/systemd/user/backup-fish-history.service - systemd.unit(5)
[Unit]
Description=Backup fish history
After=network.target

[Service]
ExecStart=/usr/bin/rsync -avh %h/.local/share/fish/fish_history framboise:backup/%H/

Activate the timer

systemctl --user enable --now backup-fish-history.timer

2. List timer units

systemctl [--user] list-timers --all

3. Watch file for changes

Start the associated service unit (foo.service) whenever the file ~/foo.txt changes (%h is a specifier that expands to the user home directory).

User units are stored in ~/.config/systemd/user/.

# ~/.config/systemd/user/foo.path - systemd.path(5)
[Unit]
Description=Monitor foo.txt for changes

[Path]
PathChanged=%h/foo.txt
Unit=foo.service

4. Run a command on login

User units are stored in ~/.config/systemd/user/ and once activated they start when the user login so the network connection should be ready (%h is a specifier that expands to the user home directory).

Run an ssh command on login

# ~/.config/systemd/user/tunnel.service - systemd.service(5)
[Unit]
Description=Start the SSH tunnel
After=network.target
ConditionPathExists=%h/.ssh/config

[Service]
Type=simple
ExecStart=/usr/bin/ssh tunnel
Restart=always
RestartSec=120

[Install]
WantedBy=default.target

Activate the service

systemctl --user enable --now tunnel.service

5. The systemd-analyze command

5.1. Condition

Test any directives (e.g. ConditionHost) with systemd-analyze condition.

~$ systemd-analyze condition 'ConditionPathExists=%h/documents'
test.service: ConditionPathExists=/home/alan/documents succeeded.
Conditions succeeded.
~$ systemd-analyze condition 'ConditionHost=!foo'
test.service: ConditionHost=!foo succeeded.
Conditions succeeded.

5.2. Calendar

Use OnCalendar= directive for scheduling based on wall-clock time, as monotonic clock starts at boot time (e.g. using OnUnitActiveSec=1hour instead of OnCalendar=hourly).

systemd-analyze calendar "Sun 01:00" --iteration=5

Will output

  Original form: Sun 01:00
Normalized form: Sun *-*-* 01:00:00
    Next elapse: Sun 2023-12-24 01:00:00 GMT
       From now: 5 days left
       Iter. #2: Sun 2023-12-31 01:00:00 GMT
       From now: 1 week 5 days left
       Iter. #3: Sun 2024-01-07 01:00:00 GMT
       From now: 2 weeks 5 days left
       Iter. #4: Sun 2024-01-14 01:00:00 GMT
       From now: 3 weeks 5 days left
       Iter. #5: Sun 2024-01-21 01:00:00 GMT
       From now: 1 month 3 days left

6. Reload unit after changing its file

systemctl [--user] daemon-reload

7. Temporary files/directories with systemd-tmpfiles

See notes:tmpfiles.d

Creates, deletes, and cleans up volatile and temporary files and directories.

8. About poweroff, shutdown and reboot commands symlinked to systemctl

See notes:ln

The systemctl command knows when it has been invoked via symlink (argument $0 returns the executed command name).

~$ ls -l /usr/sbin/poweroff
lrwxrwxrwx 1 root root 14  6 mars  15:56 /usr/sbin/poweroff -> /bin/systemctl
~$ cat foo
#!/bin/sh
echo "Invoked by $0"
~$ ln -sv foo bar
'bar' -> 'foo'
~$ ./foo
Invoked by ./foo
~$ ./bar
Invoked by ./bar

9. Related nodes

10. References

jeu. 13 août 2026

Generated with Emacs 30.1 (Org mode 9.7.11)