0

On my Gentoo Linux with dunstify as a notification daemon and StumpWM as a window manager, I wrote the following bash-script that is meant to inform me about my battery status:

#!/bin/bash
#This script notifies you if your battery is under 80% and puts the laptop to sleep in 5min if it is under 50% and isn't plugged in within that time.

if ! [ -z "$(acpi -b | cut -c 25)" ] && [[ $(acpi -b | cut -c 25) -lt 8 ]] && ! [[ "$(  acpi -b | cut -c 28)" == "%" ]]
then if ! [ -z "$(acpi -b | cut -c 25)" ] && [[ $(acpi -b | cut -c 25) -lt 5 ]] && ! [[ "$(acpi -b | cut -c 28)" == "%" ]]
     then dunstify "Battery <50" "Battery under 50%, will sleep in 5min."
          sleep 5m
          if ! [ -z "$(acpi -b | cut -c 25)" ] && [[ $(acpi -b | cut -c 25) -lt 5 ]] && ! [[ "$(acpi -b | cut -c 28)" == "%" ]]
          then sudo systemctl suspend
          fi
     else dunstify "Battery <80" "Battery under 80%."
     fi
fi

This works when I trigger it manually. However, it's supposed to be periodically triggered by systemd every 10min or so and notify me if my battery is low. So I wrote the following systemd-service:

[Unit]
Description=Checks your battery.
RefuseManualStart=no
RefuseManualStop=yes
 
[Service]
Type=oneshot
ExecStart=/bin/battery

If the battery is above 80%, the service finishes without a problem, as it should. However, if it is below 80% it exits with an error. Looking at the log, I find the following:

░░ A start job for unit battery.service has begun execution.
░░ 
░░ The job identifier is 79311.
Jul 10 16:02:54 gentoolaptop battery[537360]: Connecting to D-Bus failed: Unable to autolaunc>Jul 10 16:02:54 gentoolaptop systemd[1]: battery.service: Main process exited, code=exited, s>░░ Subject: Unit process exited
░░ Defined-By: systemd
░░ Support: https://gentoo.org/support/
░░ 
░░ An ExecStart= process belonging to unit battery.service has exited.

I've been trying to run this as a user service, where I get this message, and as a system service, where I get told that XDISPLAY and XAUTHORITY isn't set. Why can't it send messages when triggered as a service?

5
  • it may be a problem with environment. like a cronjob or whatever. Just add the PATH your script need at the begining of the script and it will work. look for exemple at where is dunstify command. Commented Jul 10, 2024 at 15:29
  • @dominix dunstify is in /bin. I've replaced the instantiations of dunstify in the script with /bin/dunstify, but I still get the same error. I don't have cron installed because I read that I should use systemd instead. Commented Jul 10, 2024 at 15:50
  • Do you have D-Bus in "user bus" mode, that is, does echo $DBUS_SESSION_BUS_ADDRESS show a path in /run/user (instead of a path in /tmp)? Commented Jul 11, 2024 at 14:33
  • @u1686_grawity No, it shows unix:path=/tmp/dbus-WBOz1ZLHcU,guid=8d36769f902e2b818b3b87f9667eb930 Commented Jul 11, 2024 at 15:45
  • 1) Do you have a ~/.dbus/ directory? 2) Do you have a /run/user/$UID directory? 3) Does systemctl --user show-environment show DBUS_SESSION_BUS_ADDRESS? Commented Jul 11, 2024 at 15:55

2 Answers 2

1

The D-Bus session bus works similarly to the X server – there can be more than one per system, so clients must know the socket address to connect to, i.e. they need DBUS_SESSION_BUS_ADDRESS= which is the rough equivalent of DISPLAY=.

(This is distinct from the system bus which has a global socket address but only lets you talk to system services.)

So you must have the …_BUS_ADDRESS show up in systemctl --user show-environment alongside DISPLAY and XAUTHORITY; it might be easiest to do this by making sure your ~/.xinitrc (or other X startup script) calls systemctl --user import-environment [...] after starting the session bus.


There are two ways of starting a session bus:

  • Traditional "session bus": At a randomly generated address under /tmp.

  • Systemd-style "user bus": At a fixed location $XDG_RUNTIME_DIR/bus (/run/user/UID/bus).

It would be best to switch your system to the second method – I'm not entirely sure how that's done in Gentoo, but I think it requires building dbus with the systemd useflag, so that it would install dbus.service and dbus.socket user units, and removing any use of dbus-launch or dbus-run-session from your ~/.xinitrc or other X startup scripts.

Then your systemd --user instance will automatically start the bus at the "well known" location under /run/user (to be shared between your X session, all your tty sessions, and your services); some D-Bus clients will be able to find it there by default, but pam_systemd will also set DBUS_SESSION_BUS_ADDRESS to that location, and systemd --user itself will automatically know it.

1
  • So, I've looked and I have compiled dbus with the systemd flag, and I have dbus services. I've tried starting the dbus user service and then the dbus session variable was completely unset in that terminal. In another terminal I've tried starting the battery service again though and it didn't work, but the status of the dbus service seems to have registered it, as checking its status shows: Activating via systemd: service name='org.freedesktop.Notifications' unit='dunst.service' and then Failed to activate service 'org.freedesktop.Notifications': timed out (service_start_timeout=120000ms) Commented Jul 13, 2024 at 13:19
0

It seems the problem for why my user systemd-service could communicate through dbus was that I was using startx to start my window manager but did not have the line

source /etc/X11/xinit/xinitrc.d/50-systemd-user.sh 

in my .xinitrc, which I apparently should have put in at a position before the window manager in executed. With this line set now, the service works as it should.

1
  • I just realized that the reason runuser didn't work for you is probably that your packages are built against elogind. I feel like you should switch away from it and build your packages (like pambase) against systemd, so that you'll get sessions with XDG_RUNTIME_DIR and DBUS_SESSION_BUS_ADDRESS set OOTB (and you won't need / shouldn't use dbus-launch in ~/.xinitrc then). Commented Jul 27, 2024 at 8:45

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.