Running a looping script with a systemd unit on boot

Hello!

I have written a script that checks the name of the wifi network I am connected to every ten seconds and runs different programs accordingly. I am trying to get it to run on startup with a systemd unit, and I cannot get it to work after a few hours of trying. I would be happy to provide further clarification if any information provided is insufficient.

Here are the relevant parts of my configuration.nix:

    home.file = { "/home/user/Scripts/wifidetector.sh" = { text = ''
      #!/bin/bash
      # This file is declared in /etc/nixos/configuration.nix.

      # -- SET VARIABLES -- #
      var=0

      # -- UNCONDITIONAL AUTOSTARTS -- #
      signal-desktop &
      flatpak update --assumeyes --verbose &
      flatpak update --assumeyes --verbose --user &

      while [ 1 -eq 1 ]
      do
          sleep 10
          myssid=$(iwgetid -r)
          echo $myssid

          if [ "$myssid" = "ssid1" ]; then
              
              killall qbittorrent
              killall electron  # Kills Vesktop. This might cause issues in the future, not sure how to make it better

              if [ $var != 1 ]; then
                  qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.setBrightness $(expr $(qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightness) = 0)  # Set brightness to 0
                  sleep 0.1
                  qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.setBrightness $(expr $(qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightness) + 38000)  # Increase brightness by 40%
                  pactl set-sink-volume @DEFAULT_SINK@ 0  # Set volume to 0
              fi

              var=1

          elif [ "$myssid" = "ssid2" ]; then
              if [ $var != 2 ]; then
                  qbittorrent &  # Start qbittorrent
                  vesktop --start-minimized &  # Start Vesktop
                  qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.setBrightness $(expr $(qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightness) = 0)  # Set brightness to 0
                  sleep 0.1
                  qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.setBrightness $(expr $(qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightness) + 48000)  # Increase brightness by 50%
                  sleep 0.1
                  qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.setBrightness $(expr $(qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightness) + 48000)  # Increase brightness by 50%
                  pactl set-sink-volume @DEFAULT_SINK@ 0.062  # Set volume to 40%
              fi

              var=2
          fi
          
      done
    '';
    executable = true;
    };};
  systemd.services.wifiDetector = {
    wantedBy = [ "network-online.target" ];
    description = "Runs wifidetector.sh";
    serviceConfig = {
      Type = "oneshot";
      RemainAfterExit = "yes";
      User = "user";
      ExecStart = "${pkgs.fish}/bin/fish -lc 'nohup /home/user/Scripts/wifidetector.sh &'"; 
    };
  }; 

I know it’s not the cleanest way to do things, but I just want something that works right now.

The script works as expected when executed in my terminal. Here is the relevant part of the journalctl log when the unit is run under wifi ssid2:

fish[10766]: error: There were one or more errors
fish[10763]: /home/user/Scripts/wifidetector.sh: line 49: 10765 Segmentation fault      (core dumped) signal-desktop
fish[10763]: ssid2
fish[10963]: Could not connect to D-Bus server: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11
fish[10962]: expr: syntax error: unexpected argument ‘0’
fish[10965]: Could not connect to D-Bus server: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11
qbittorrent[10960]: qt.qpa.xcb: could not connect to display
qbittorrent[10960]: qt.qpa.plugin: From 6.5.0, xcb-cursor0 or libxcb-cursor0 is needed to load the Qt xcb platform plugin.
qbittorrent[10960]: qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
qbittorrent[10960]: This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
                                                   
                                                   Available platform plugins are: wayland-egl, wayland, eglfs, minimalegl, offscreen, vkkhrdisplay, xcb, linuxfb, minimal, vnc.
fish[10994]: Could not connect to D-Bus server: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11
fish[11002]: Could not connect to D-Bus server: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11
fish[10763]: /home/user/Scripts/wifidetector.sh: line 49: 10960 Aborted                 (core dumped) qbittorrent
fish[11010]: Could not connect to D-Bus server: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11
fish[11012]: Could not connect to D-Bus server: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11
fish[10961]: Vesktop is already running. Quitting...
fish[10961]: [10961:1110/215414.978575:ERROR:ozone_platform_x11.cc(245)] Missing X server or $DISPLAY
fish[10961]: [10961:1110/215414.978611:ERROR:env.cc(258)] The platform failed to initialize.  Exiting.
pulseaudio[11025]: [pulseaudio] main.c: Daemon startup without any loaded modules, refusing to work.
pulseaudio[11017]: [pulseaudio] main.c: Daemon startup failed.
fish[11015]: Connection failure: Connection refused
fish[11015]: pa_context_connect() failed: Connection refused
fish[10763]: /home/user/Scripts/wifidetector.sh: line 49: 10961 Segmentation fault      (core dumped) vesktop --start-minimized
fish[10763]: ssid2

If it matters, I am on NixOS 24.05 running KDE on Wayland.

you need to set the desktop/WM specific env vars for graphical applications to work (systemd services don’t inherit your session variables) like WAYLAND_DISPLAY.

I just used KDE Autostart and it works okay for now