Search code examples
x11dbusawesome-wm

Running awesome-client from a script executing as root


Running Awesome on Debian (11) testing

awesome v4.3 (Too long)
 • Compiled against Lua 5.3.3 (running with Lua 5.3)
 • D-Bus support: ✔
 • execinfo support: ✔
 • xcb-randr version: 1.6
 • LGI version: 0.9.2

I'm trying to signal to Awesome when systemd triggers suspend. After fiddling with D-Bus directly for awhile and getting nowhere, I wrote a couple of functions that somewhat duplicate the functionality of signals.

I tested it by running the following command in a shell, inside of my Awesome session:

$ awesome-client 'require("lib.syskit").signal("awesome-client", "Hello world!")'

This runs just fine. A notification posts to the desktop "Hello world!" as expected. I added the path to my lib.syskit code to the $LUA_PATH in my ~/.xsessionrc. Given the error described below, I doubt this is an issue.

Now for the more difficult part. I put the following in a script located at /lib/systemd/system-sleep/pre-suspend.sh

#!/bin/bash

if [ "${1}" == "pre" ]; then
    ERR=$(export DISPLAY=":0"; sudo -u naddan awesome-client 'require("lib.syskit").signal("awesome-client", "pre-suspend")' 2>&1)
    echo "suspending at `date`, ${ERR}" > /tmp/systemd_suspend_test
elif [ "${1}" == "post" ]; then
    ERR=$(export DISPLAY=":0"; sudo -u naddan awesome-client 'require("lib.syskit").signal("awesome-client", "post-suspend")' 2>&1)
    echo "resuming at `date`, ${ERR}" >> /tmp/systemd_suspend_test
fi

Here's the output written to /tmp/systemd_suspend_test

suspending at Thu 22 Jul 2021 10:58:01 PM MDT, Failed to open connection to "session" message bus: /usr/bin/dbus-launch terminated abnormally without any error message                                        
E: dbus-send failed.
resuming at Thu 22 Jul 2021 10:58:05 PM MDT, Failed to open connection to "session" message bus: /usr/bin/dbus-launch terminated abnormally without any error message
E: dbus-send failed.

Given that I'm already telling it the $DISPLAY that Awesome is running under (this is a laptop), and that I'm running awesome-client as my user, not root, what else am I missing that's keeping this from working?

Is there a better way that I could achieve telling Awesome when the system suspends?


Solution

  • awesome-client is a shell script. It is a thin wrapper around dbus-send. Thus, since you write "After fiddling with D-Bus directly for awhile and getting nowhere", I guess the same reasoning applies.

    Given that I'm already telling it the $DISPLAY that Awesome is running under (this is a laptop), and that I'm running awesome-client as my user, not root, what else am I missing that's keeping this from working?

    You are missing the address of the dbus session bus. For me, it is:

    $ env | grep DBUS
    DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
    

    Is there a better way that I could achieve telling Awesome when the system suspends?

    Instead of sending a message directly to awesome via some script, you could use the existing mechanism for this: Dbus signals. These are broadcasts that interested parties can listen to.

    Google suggests that there is already a PrepareForSleep signal:

    https://serverfault.com/questions/573379/system-suspend-dbus-upower-signals-are-not-seen

    Based on this, Google then gave me the following AwesomeWM lua code that listens for logind's PrepareForSleep signal (written by yours truely - thanks Google for finding that!):

    https://github.com/awesomeWM/awesome/issues/344#issuecomment-328354719

    local lgi = require("lgi")
    local Gio = lgi.require("Gio")
    
    local function listen_to_signals()
        local bus = lgi.Gio.bus_get_sync(Gio.BusType.SYSTEM)
        local sender = "org.freedesktop.login1"
        local interface = "org.freedesktop.login1.Manager"
        local object = "/org/freedesktop/login1"
        local member = "PrepareForSleep"
        bus:signal_subscribe(sender, interface, member, object, nil, Gio.DBusSignalFlags.NONE,
        function(bus, sender, object, interface, signal, params)
            -- "signals are sent right before (with the argument True) and
            -- after (with the argument False) the system goes down for
            -- reboot/poweroff, resp. suspend/hibernate."
            if not params[1] then
                -- This code is run before suspend. You can replace the following with something else.
                require("gears.timer").start_new(2, function()
                    mytextclock:force_update()
                end)
            end
        end)
    end
    
    listen_to_signals()