Systemd timers and service

Hi all,

I have a question about systemd .timer and .service functionality.
I’m trying to find a way to open VLC in terminal (nvlc) and start a radio stream at a specific time.
The end goal is to have my computer wake up from suspend and start playing music in the mornings.
This is what I have so far:

radio.timer:

    [Unit]
    Description=Stream radio through nvlc

    [Timer]
    # Run the service every day
    #OnCalendar=*-*-* 07:30:00
    OnUnitActiveSec=2min
    WakeSystem=true
    Unit=radio.service

    [Install]
    #WantedBy=default.target
    #WantedBy=multi-user.target
    WantedBy=timers.target

radio.service:

    [Unit]
    Description=Stream radio through nvlc
    StopWhenUnneeded=true

    [Service]
    Type=simple
    User=bart
    Group=users
    #Environment="QT_PLUGIN_PATH=/usr/lib64/qt5/plugins/platforms"
    #Environment="QT_QPA_PLATFORM=/usr/lib64/qt5/plugins/platforms"
    Environment="QT_QPA_PLATFORM_PLUGIN_PATH=/usr/lib64/qt5/plugins/platforms"
    ExecStart=/home/bart/bin/scripts/radio.sh

    [Install]
    #WantedBy=default.target
    WantedBy=multi-user.target

radio.sh:

    #!/bin/bash
    konsole --new-tab -e "nvlc http://ais-edge23-dal02.cdnstream.com:80/1340_128"

The timer works, it triggers the radio.service every 2mins (for testing).
The script - when run as regular user - runs fine.

The problems happen when the .service file tries to run the script. I reaches the konsole command but then throws an “xcb” error, see screenshot:


I get this with or without the QT_QPA_PLATFORM_PLUGIN_PATH env var.

I’m guessing this has to do with running the script through systemd and not a regular user ?
Also not sure about the WantedBy= directives…
How do solve this?

TIA
Bart.

I never tried this, thus my experience is nil.

But I see some missing steps.

You do not show where all those files are (we prefer to seen complete command/ouput copy/pastes, in this case the cat statements are missing). Are these system or user files?

Then you say your system “wakes up from suspend”, but you do not tell how (maybe I am to stupid to understand this). But there is no information on in what status the system is the. Are there one or more users logged in (in the CLI or in the GUI). You are talking about konsole, thus it looks as if you assume that there is at least one user logged in in the GUI and uses KDE. Is that true?

Then, when these systemd files are managed on the system level, it is clear that what is defined in ExecStart is started as a root owned process in the background. That process will not know where to open the window with konsole.

I created the following user service on infamous host erlangen by running systemctl edit --user --force --full radio.service:

karl@erlangen:~> systemctl --user cat radio
# /home/karl/.config/systemd/user/radio.service
[Unit]
Description=Stream radio through nvlc

[Service]
ExecStart=/usr/bin/nvlc http://ais-edge23-dal02.cdnstream.com:80/1340_128
karl@erlangen:~> 

Starting the service with systemctl --user start radio plays music on host erlangen.

Yes, of course, that works. The problem is the combination with wake up from suspend.

AFAIK, the wake up can only be done through system service, not a user service.
But I haven’t even gotten to that part yet, I’m still trying to run the script as the given user/group (as given in {Service} block).
Manual says to use those directives to “override” the root user which runs the service manager (at least, that’s my understanding).

Suspending the host to RAM will pause radio.timer. Wakeup needs to triggered from outside.

Even if it runs as user bart (in the background), it still does not know that it must use some DISPLAY to open the window on. You forgot that Unix/Linux is a multi-user/multi-session system. There can be nil, one, two or more GUI sessions running when that script starts. Which one to use? And then still that user will normally have blocked the outside world from opening windows in his/her session (imagine when every user on the system could open windows in your personal session, that would include an invisible window over the whole space that even could see what you type).

1 Like

I doubt. When the system sleeps, no systemd deamon will run to activate services. Thus my question (you did not answer) how is the “wake from suspend” done>

You could try man systemd.timer and search for WakeSystem.

Thanks for that.

I do not really understand all the implications. But you say it works for you (that is the system resumes, not the music, that comes later).

Program started outside of your session knows nothing about X11/Wayland server it needs to connect to nor does it have any of the environment usually set when your session is started. If your user session (and so systemd instance) remains active, you can initiate user service using

systemd-run --user -M bart@.host /home/bart/bin/scripts/radio.sh

It will connect to your systemd user instance and create transient service running the given command in your user environment. See man systemd-run for details.

Another thing (which @karlmistelberger pointed to without much explanation) is why the script that calls konsole that calls nvlc?

Actually systemctl supports -M option as well, so you can create your user service and start it from within other system service using

systemctl --user -M bart@.host start radio.service
1 Like

Testet the following:

erlangen:~ # systemctl cat radio0*
# /etc/systemd/system/radio0.service
[Unit]
Description=Stream radio through nvlc

[Service]
ExecStart=/usr/bin/systemctl -M karl@.host  start --user radio.service

# /etc/systemd/system/radio0.timer
[Unit]
Description=Stream radio through nvlc

[Timer]
OnUnitActiveSec=1min
WakeSystem=true

[Install]
WantedBy=timers.target
erlangen:~ # 

The above plays music every minute.

1 Like

Bye the way:

erlangen:~ # systemctl status init.scope 
● init.scope - System and Service Manager
     Loaded: loaded
  Transient: yes
     Active: active (running) since Thu 2023-06-01 07:25:36 CEST; 47min ago
       Docs: man:systemd(1)
      Tasks: 1 (limit: 4915)
        CPU: 1.691s
     CGroup: /init.scope
             └─1 /usr/lib/systemd/systemd --switched-root --system --deserialize=39

Jun 01 08:05:01 erlangen systemd[1]: Started Stream radio through nvlc.
Jun 01 08:05:01 erlangen systemd[1]: Started systemd-stdio-bridge -punix:path=${XDG_RUNTIME_DIR}/bus.
Jun 01 08:05:01 erlangen systemd[1]: Started Session 9 of User karl.
Jun 01 08:05:01 erlangen systemd[1]: run-u129.service: Deactivated successfully.
Jun 01 08:05:01 erlangen systemd[1]: radio0.service: Deactivated successfully.
Jun 01 08:05:01 erlangen systemd[1]: session-9.scope: Deactivated successfully.
Jun 01 08:06:37 erlangen systemd[1]: Started systemd-stdio-bridge.
Jun 01 08:06:37 erlangen systemd[1]: Started Session 10 of User karl.
Jun 01 08:06:37 erlangen systemd[1]: run-u133.service: Deactivated successfully.
Jun 01 08:06:37 erlangen systemd[1]: session-10.scope: Deactivated successfully.
erlangen:~ # 

User systemd:

karl@erlangen:~> systemctl status --user init.scope
● init.scope - System and Service Manager
     Loaded: loaded
  Transient: yes
     Active: active (running) since Thu 2023-06-01 07:26:02 CEST; 47min ago
       Docs: man:systemd(1)
      Tasks: 2 (limit: 4915)
     Memory: 3.9M
        CPU: 326ms
     CGroup: /user.slice/user-1000.slice/user@1000.service/init.scope
             ├─6082 /usr/lib/systemd/systemd --user
             └─6083 "(sd-pam)"

Jun 01 07:35:01 erlangen systemd[6082]: Started Stream radio through nvlc.
Jun 01 07:35:07 erlangen systemd[6082]: radio.service: Consumed 5.702s CPU time.
Jun 01 07:46:26 erlangen systemd[6082]: Started KMail - Mail Client.
Jun 01 07:54:38 erlangen systemd[6082]: Started KMail - Mail Client.
Jun 01 07:55:06 erlangen systemd[6082]: Started Firefox - Web Browser.
Jun 01 07:58:53 erlangen systemd[6082]: Started Firefox - Web Browser.
Jun 01 08:03:01 erlangen systemd[6082]: Started Stream radio through nvlc.
Jun 01 08:03:08 erlangen systemd[6082]: radio.service: Consumed 6.788s CPU time.
Jun 01 08:05:01 erlangen systemd[6082]: Started Stream radio through nvlc.
Jun 01 08:05:16 erlangen systemd[6082]: radio.service: Consumed 14.471s CPU time.
karl@erlangen:~> 

Ok thanks for your replies, everyone.
So I followed the path @arvidjaar and @karlmistelberger suggested and managed to get the music playing :slight_smile:
This brings me to the last step; putting it all together and have the system wake up from sleep through the timer.

To summarize; the workflow ATM is as follows:

  • I’m the sole user of the system, logged in all the time
  • putting system into sleep / suspend is done with power button / Ctrl+Alt+Del → select “Sleep”
  • radio.timer should wake system @ fixed time (OnCalendar= ) and execute radio-trigger.service
  • radio-trigger.service executes user service (radio.service)

According to systemd.timer man pages:

OnCalendar= uses wallclock timer, not monotonic
WakeSystem= a different monotonic clock (CLOCK_BOOTTIME) is selected that continues to advance while the system is suspended and thus can be used as the trigger to resume the system.

The problem now is that if I enable WakeSystem, this actually prevents the system going into sleep mode.
I get this in dmesg output:

PM: suspend entry (shallow)
    [103158.437593] Filesystems sync: 0.014 seconds
    ...
    [103158.613636] sd 0:0:0:0: [sda] Stopping disk
    [103159.714554] PM: Some devices failed to suspend, or early wake event detected
    [103159.714923] sd 0:0:0:0: [sda] Starting disk
    ...

My current files are:
/etc/systemd/system/radio.timer

[Unit]
Description=Trigger radio-trigger.service

[Timer]
# Run the service every day
OnCalendar=*-*-* 07:30:00
WakeSystem=true
Unit=radio-trigger.service

[Install]
WantedBy=timers.target

/etc/systemd/system/radio-trigger.service

[Unit]
Description=User radio service
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl --user -M bart@.host start radio.service

~/.config/systemd/user /radio.service

[Unit]
Description=Play Radio stream on wakeup

[Service]
Type=simple
ExecStart=/usr/bin/konsole --new-tab -e "nvlc http://ais-edge23-dal02.cdnstream.com:80/1340_128"

[Install]
WantedBy=multi-user.target

Any more insight is welcome, or alternative way to wake from suspend (cron ?)…
I’ve read a lot these days but nothing suggests this shouldn’t work…

TIA
Bart.

I take the liberty to also quote from the man page:

WakeSystem=
Takes a boolean argument. If true, an elapsing timer will cause the system to resume from suspend, should it be suspended and if the system supports this. Note that this option will only make sure the system resumes on the appropriate times, it will not take care of suspending it again after any work that is to be done is finished. Defaults to false.

The bold part is mine. This points IMHO to the hardware/firmware of the system. Either it can, it can not, or it is configurable in the BIOS/UEFI.

BTW, it is still not clear to me why you want to run the music program with a terminal emulator (konsole). Direct starting it seems more logical to me. Or am I missing something?

ExecStart=/usr/bin/nvlc http://ais-edge23--dal02.cdnstream.com:80/1340_128

Thank you, I noticed that part too.
Obviously, my computer can go into suspend mode - and resume - because I’ve been doing that (manually) for 10+ years now :wink:
I don’t see why it wouldn’t work through a service ? Seems more like order-of-execution problem, not hardware related.

The manual also doesn’t state this option can prevent the computer from going into sleep mode either, which is what’s happening now.

On the konsole part; it’s always open and it works for now. it’s not the major issue :slight_smile:

OK seems like a permission issue, found this in journalctl:

jun 01 17:55:38 bart.tumbleweed systemd[1]: Failed to start System Suspend.
░░ Subject: A start job for unit systemd-suspend.service has failed
░░ Defined-By: systemd
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
░░
░░ A start job for unit systemd-suspend.service has finished with a failure.
░░
░░ The job identifier is 56009 and the job result is failed.
jun 01 18:01:54 bart.tumbleweed (sd-pam)[7030]: pam_systemd(login:session): Failed to release session: Access denied
jun 01 20:42:52 bart.tumbleweed sudo[13687]: pam_unix(sudo:auth): conversation failed
jun 01 20:42:52 bart.tumbleweed sudo[13687]: pam_unix(sudo:auth): auth could not identify password for [root]
jun 01 20:47:37 bart.tumbleweed kernel: PM: Some devices failed to suspend, or early wake event detected
jun 01 20:47:43 bart.tumbleweed kernel: PM: Some devices failed to suspend, or early wake event detected
jun 01 20:47:48 bart.tumbleweed kernel: PM: Some devices failed to suspend, or early wake event detected
jun 01 20:47:48 bart.tumbleweed systemd-sleep[14060]: Failed to put system to sleep. System resumed again: Device or resource busy
░░ Subject: System sleep state suspend left
░░ Defined-By: systemd
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
░░
░░ The system has now left the suspend sleep state.

Great insight from infamous host erlangen: it works. :wink:

erlangen:~ # journalctl --since 08:54 -u systemd-suspend.service -u radio0.timer -u radio0.service
Jun 02 08:54:21 erlangen systemd[1]: radio0.timer: Deactivated successfully.
Jun 02 08:54:21 erlangen systemd[1]: Stopped Stream radio through nvlc.
Jun 02 08:54:21 erlangen systemd[1]: Stopping Stream radio through nvlc...
Jun 02 08:54:21 erlangen systemd[1]: Started Stream radio through nvlc.
Jun 02 08:54:33 erlangen systemd[1]: Starting System Suspend...
Jun 02 08:54:33 erlangen systemd-sleep[24658]: INFO: Skip running /usr/lib/systemd/system-sleep/grub2.sleep for suspend
Jun 02 08:54:33 erlangen systemd-sleep[24656]: Entering sleep state 'suspend'...
Jun 02 08:55:08 erlangen systemd-sleep[24656]: System returned from sleep state.
Jun 02 08:55:09 erlangen systemd-sleep[24685]: INFO: Skip running /usr/lib/systemd/system-sleep/grub2.sleep for suspend
Jun 02 08:55:09 erlangen systemd[1]: Started Stream radio through nvlc.
Jun 02 08:55:09 erlangen systemd[1]: systemd-suspend.service: Deactivated successfully.
Jun 02 08:55:09 erlangen systemd[1]: Finished System Suspend.
Jun 02 08:55:09 erlangen systemd[1]: radio0.service: Deactivated successfully.
erlangen:~ # 

User journal:

karl@erlangen:~> journalctl --since 08:54 --user --unit init.scope 
Jun 02 08:55:09 erlangen systemd[6082]: Started Stream radio through nvlc.
Jun 02 08:55:09 erlangen systemd[6082]: Starting KScreen OSD service...
Jun 02 08:55:09 erlangen systemd[6082]: Started KScreen OSD service.
Jun 02 08:56:07 erlangen systemd[6082]: radio.service: Consumed 58.255s CPU time.
karl@erlangen:~> 

erlangen smoothly suspended, resumed and played music.

erlangen:~ # systemctl cat radio0.timer
# /etc/systemd/system/radio0.timer
[Unit]
Description=Stream radio through nvlc

[Timer]
OnCalendar=*-*-* 08:55:00
WakeSystem=true

[Install]
WantedBy=timers.target
erlangen:~ # 
erlangen:~ # systemctl cat radio0.service 
# /etc/systemd/system/radio0.service
[Unit]
Description=Stream radio through nvlc

[Service]
ExecStart=/usr/bin/systemctl -M karl@.host  start --user radio.service
erlangen:~ # 
karl@erlangen:~> systemctl cat --user radio.service 
# /home/karl/.config/systemd/user/radio.service
[Unit]
Description=Stream radio through nvlc

[Service]
ExecStart=/usr/bin/nvlc http://ais-edge23-dal02.cdnstream.com:80/1340_128
karl@erlangen:~> 

Congratulations. Looks neat and clean.