Systemd timer as user - not starting at boot

I’m trying to create a service for a user that activates every 10 minutes. Everything works if I start the timer manually, but after a restart it’s inactive. What am I doing wrong?

[Unit]
Description=HyperHDR Night switch

[Service]
Type=simple
ExecStart=/home/mike/Skrypty/night_led.sh
[Unit]
Description=Run my script every 10 minutes
  
[Timer]
OnCalendar=*:0/10
Persistent=true
OnBootSec=10
    
[Install]
WantedBy=timers.target

after boot:

systemctl --user status hyperhdr-switch.timer
○ hyperhdr-switch.timer - Run my script every 10 minutes
     Loaded: loaded (/home/mike/.config/systemd/user/hyperhdr-switch.timer; enabled; preset: enabled)
     Active: inactive (dead)
    Trigger: n/a
   Triggers: ● hyperhdr-switch.service

and after systemctl --user start hyperhdr-switch.timer

● hyperhdr-switch.timer - Run my script every 10 minutes
     Loaded: loaded (/home/mike/.config/systemd/user/hyperhdr-switch.timer; enabled; preset: enabled)
     Active: active (waiting) since Wed 2024-12-18 10:40:19 CET; 2s ago
 Invocation: ec8854326b654f889386cb23cd0212b6
    Trigger: Wed 2024-12-18 10:41:00 CET; 37s left
   Triggers: ● hyperhdr-switch.service

gru 18 10:40:19 ryzen systemd[884]: Started Run my script every 10 minutes.

systemctl enable --now hyperhdr-switch.timer

Do not use sudo.

timers and services for specific user is placed in ~/.config/systemd/user

And the enable of the timer (no sudo and add --user)

systemctl enable --user my-timer.timer
1 Like

i already do that. The timer is showing an “enabled” status, but it becomes inactive after a restart. I know I could add a command “systemctl enable --user my-timer.timer” to the startup programs, but that defeats the whole purpose of services.

mike@ryzen ~ [1]> ls ~/.config/systemd/user/
hyperhdr-switch.service  hyperhdr-switch.timer  timers.target.wants/
mike@ryzen ~> ls ~/.config/systemd/user/timers.target.wants/
hyperhdr-switch.timer@

it’s enabled but not started after reboot…

 systemctl --user list-timers --all
NEXT LEFT LAST PASSED UNIT                  ACTIVATES              
-       - -         - hyperhdr-switch.timer hyperhdr-switch.service

1 timers listed.

i need to start it manually

systemctl --user status hyperhdr-switch.timer
○ hyperhdr-switch.timer - Run my script every 10 minutes
     Loaded: loaded (/home/mike/.config/systemd/user/hyperhdr-switch.timer; enabled; preset: enabled)
     Active: inactive (dead)
    Trigger: n/a
   Triggers: ● hyperhdr-switch.service
mike@ryzen ~ [3]> systemctl --user start hyperhdr-switch.timer
mike@ryzen ~> systemctl --user status hyperhdr-switch.timer
● hyperhdr-switch.timer - Run my script every 10 minutes
     Loaded: loaded (/home/mike/.config/systemd/user/hyperhdr-switch.timer; enabled; preset: enabled)
     Active: active (running) since Wed 2024-12-18 11:57:58 CET; 2s ago
 Invocation: b09f1467db024df3939482e4637e8e09
    Trigger: n/a
   Triggers: ● hyperhdr-switch.service

gru 18 11:57:58 ryzen systemd[894]: Started Run my script every 10 minutes.
mike@ryzen ~> systemctl --user list-timers --all
NEXT                        LEFT LAST                        PASSED UNIT                  ACTIVATES              
Wed 2024-12-18 11:59:00 CET  53s Wed 2024-12-18 11:58:00 CET 5s ago hyperhdr-switch.timer hyperhdr-switch.service

1 timers listed.

This is very soon after login, are you sure your system is ready? Do you checked the user journal for entries for entries that soon after a login?

A setting like OnUnitActiveSec=10min or OnUnitInactiveSecc=10min might be more approbiert then OnCalendar

Also this

Wed 2024-12-18 11:59:00 CET  53s Wed 2024-12-18 11:58:00 CET 5s

does not look like OnCalendar=*:0/10

1 Like

Your hyperhdr-switch.service file looks fine:

[Unit]
Description=HyperHDR Night switch

[Service]
Type=simple
ExecStart=/home/mike/Skrypty/night_led.sh

However, your hyperhdr-switch.timer file should use OnUnitActiveSec= rather than OnCalendar= if it is just going to run every 10 minutes.

Also, as it will be run as a user, OnStartupSec= should be used rather than OnBootSec= so that it starts when the user account logs in.

Try this:

hyperhdr-switch.timer:

[Unit]
Description=Run my script every 10 minutes
# Allow manual starts
RefuseManualStart=no
# Allow manual stops
RefuseManualStop=no

[Timer]
Persistent=true
OnStartupSec=10
OnUnitActiveSec=10 min
Unit=hyperhdr-switch.service
    
[Install]
WantedBy=timers.target
1 Like

i know, for test i used 1min timer.

still the same. no start at login.

for now i just used systemctl --user start hyperhdr-switch.timer in Cinnamon Startup Programs and it works.

You need to enable the timer:

systemctl --user enable --now hyperhdr-switch.timer

it is already enabled. the timer service just not starting at login.

Could you please confirm that your ~/.config/systemd/user/ directory contains the files hyperhdr-switch.service & hyperhdr-switch.timer?

Also, please confirm that your ~/.config/systemd/user/timers.target.wants/ directory contains hyperhdr-switch.timer as a symlink to ~/.config/systemd/user/hyperhdr-switch.timer.

If they look fine, then try the following commands:

systemctl --user disable --now hyperhdr-switch.timer

then

systemctl --user enable --now hyperhdr-switch.timer

Please make a note of any warnings or error messages that occur when you enable the timer and post them here.

Also, as the timer is not starting at login, maybe you should give the system a little more time to load the desktop and services before starting it. Would making the timer wait 30-60 seconds cause any issues? That would just require a change to the OnStartupSec=10 line.

After you make any changes and save the file, make sure you run:

systemctl --user daemon-reload
1 Like

Example of service/timer construct.
source → [root tip] [HowTo] Check if your AUR build scripts have been updated

 $ cat check-aur.service
[Unit]
Description=Check for changes to AUR buildscrpts
# wait for network
After=syslog.target network.target default.target

[Service]
Type=simple
ExecStartPre=/bin/sleep 30
ExecStart=/home/%u/.local/bin/check-aur.sh

[Install]
WantedBy=default.target
 $ cat check-aur.timer
[Unit]
Description=Schedule AUR change checks

[Timer]
OnStartupSec=10m
OnUnitActiveSec=4h

[Install]
WantedBy=timers.target
mike@ryzen ~> systemctl --user daemon-reload
mike@ryzen ~> systemctl --user reenable hyperhdr-switch.timer
Removed '/home/mike/.config/systemd/user/timers.target.wants/hyperhdr-switch.timer'.
Created symlink '/home/mike/.config/systemd/user/timers.target.wants/hyperhdr-switch.timer' → '/home/mike/.config/systemd/user/hyperhdr-switch.timer'.
mike@ryzen ~> ls -l ~/.config/systemd/user/
razem 12
-rw-r--r-- 1 mike mike  143 12-18 10:32 hyperhdr-switch.service
-rw-r--r-- 1 mike mike  149 12-19 08:55 hyperhdr-switch.timer
drwxr-xr-x 2 mike mike 4096 12-19 08:55 timers.target.wants/
mike@ryzen ~> ls -l ~/.config/systemd/user/timers.target.wants/
razem 4
lrwxrwxrwx 1 mike mike 53 12-19 08:55 hyperhdr-switch.timer -> /home/mike/.config/systemd/user/hyperhdr-switch.timer

changed OnStartupSec=60

mike@ryzen ~> uptime -p
up 3 minutes
mike@ryzen ~> systemctl --user status hyperhdr-switch.timer
○ hyperhdr-switch.timer - Run my script every 10 minutes
     Loaded: loaded (/home/mike/.config/systemd/user/hyperhdr-switch.timer; enabled; preset: enabled)
     Active: inactive (dead)
    Trigger: n/a
   Triggers: ● hyperhdr-switch.service

nothing changed. I give up, I will start the timer service by cinnamon startup scripts.

Try simplifying your timer

Having 10 min is not correct - it should be 10min

[Unit]
Description=Run my script every 10 minutes

[Timer]
OnStartupSec=10
OnUnitActiveSec=10min
    
[Install]
WantedBy=timers.target

timer/service construct follows naming convention (your naming is correct)

unit-name.timer
unit-name.service

This construct makes the Unit= obsolete as it is inferred from the name.
Persisistent does not need to be set - it will work.

[Unit]
Description=HyperHDR Night switch

[Service]
Type=simple
ExecStart=/home/mike/Skrypty/night_led.sh

Try moving the script to your ~/.local/bin folder, make sure it is executable and change to

ExecStart=/home/%u/.local/bin/night_led.sh

Then verify that your script works as expected when executed from CLI.

I would also experiment with the [Install] section in the service file

[Install]
WantedBy=default.target
2 Likes

I’m scratching my head too. The only suggestion I have left is to run the following commands to see if there are any issues with the hyperhdr-switch.service file that may be preventing the timer from running:

systemctl --user status hyperhdr-switch.service
journalctl --user -xeu hyperhdr-switch.service

You might as well run the journalctl on the timer as well (if you haven’t already done so):

journalctl --user -xeu hyperhdr-switch.timer

Thanks for the tip.

I’ve been using a template from the first timer I created a couple of years ago to create my timers since then. I might go through them all over the weekend & remove any unnecessary lines.

It works fine with or without spaces. Most of my timers have a space in either the OnStartupSec= or the OnUnitActiveSec= values, and they’ve worked without any problems. Although I just now removed the spaces in all of them.

Systemd is quite good at working out what the user intends when they enter a duration.