Many modern Unix/Linux GUI apps make use D-Bus for talking to one another and managing their lifecycle (ex. creating a single instance application or daemon).

In a full Ubuntu machine, systemd is started when it boots up and D-Bus is automatically configured. However, WSL2 (Windows Subsystem for Linux 2) doesn't support running systemd and you cannot automatically have the D-Bus ready when you open an Ubuntu/WSL2 console.

We prepared the following steps for setting up D-Bus daemons that can be shared in all your Ubuntu/WSL2 consoles. Although the following steps focus on Ubuntu, you should be able to set up the D-Bus similarly for your WSL2 Linux distro.

System D-Bus

Ubuntu already has a mechanism for starting a D-Bus that is available to all users and processes of the system. You can start that system bus via service command.

sudo service dbus start





Session D-Bus

If you're planning on using just a single Ubuntu console for all your Linux GUI apps, you can start a session D-Bus simply by executing the following command.

eval $(dbus-launch --sh-syntax)



Once executed, you should be able to see that DBUS_SESSION_BUS_ADDRESS environment variable is now set for your apps.

echo $DBUS_SESSION_BUS_ADDRESS



However, when you open another Ubuntu console, that newly created DBUS_SESSION_BUS_ADDRESS environment variable is not automatically carried over to that new console. You can start another session D-Bus for the new console, but your apps started in the new console cannot communicate with the apps that are started in the previous console with a different session D-Bus.

Instead of using dbus-launch and eval commands as shown above, we prepared the following Bash script for creating a session D-Bus that can be shared in all your Ubuntu consoles. Our approach makes use of the directory management behavior in WSL2.

WSL2 doesn't support running systemd for managing daemons and carrying out system tasks. However, it automatically empties /run/user directory whenever WSL is first started (ex. after rebooting Windows, or explicitly terminated and restarted by executing wsl.exe --shutdown). Hence, the following script in Step 1 checks for a D-Bus Unix socket in /run/user/$(id -u) directory and a new one is created only if it doesn't exist.

In a full Ubuntu machine, /run/user/$(id -u) directory is automatically created when you log into the system for the first time. XDG_RUNTIME_DIR environment variable is also automatically set and pointing to that directory. In order to mimic this behavior, the script in Step 1 also sets XDG_RUNTIME_DIR environment variable and creates the directory if it doesn't already exist. If the directory doesn't exist, you can safely assume that your Ubuntu/WSL2 is just launched and it's a perfect time to start additional daemons and services as shown in the script.

Create ~/.bash_sysinit

In the script shown below, you must replace <your_ubuntu_wsl2_password> with your own password that you set for Ubuntu/WSL2. If you're uncomfortable adding your password in the script, you can remove the line and enter your password directly while running the script; since you only need to enter your password once when you open an Ubuntu/WSL2 console for the first time, it shouldn't be too annoying...

~/.bash_sysinit
# X410 WSL2 Helper
# https://x410.dev/cookbook/#wsl
# --------------------
# Setting up D-Bus for Ubuntu
# --------------------

sudo_autopasswd()
{
    echo "<your_ubuntu_wsl2_password>" | sudo -Svp ""
    # Default timeout for caching your sudo password: 15 minutes

    # If you're uncomfortable entering your password here,
    # you can comment out the line above. But keep in mind that functions
    # in a Bash script cannot be empty; comment lines are ignored.
    # A function should at least have a ':' (null command).
    # https://tldp.org/LDP/abs/html/functions.html#EMPTYFUNC
}

sudo_resetpasswd()
{
    # Clears cached password for sudo
    sudo -k
}

#
# '/run/user' directory is always empty when WSL2 is first
# launched; a perfect time to setup daemons and D-Bus
#

export XDG_RUNTIME_DIR=/run/user/$(id -u)
if [ ! -d "$XDG_RUNTIME_DIR" ]; then
{
    sudo_autopasswd

    # Create user runtime directories
    sudo mkdir $XDG_RUNTIME_DIR && sudo chmod 700 $XDG_RUNTIME_DIR && sudo chown $(id -un):$(id -gn) $XDG_RUNTIME_DIR

    # System D-Bus
    sudo service dbus start

    # --------------------
    # Start additional services as they are needed.
    # We recommend adding commands that require 'sudo' here. For other
    # regular background processes, you should add them below where a
    # session 'dbus-daemon' is started.
    # --------------------

    sudo_resetpasswd
}
fi

set_session_dbus()
{
    local bus_file_path="$XDG_RUNTIME_DIR/bus"

    export DBUS_SESSION_BUS_ADDRESS=unix:path=$bus_file_path
    if [ ! -e "$bus_file_path" ]; then
    {
        /usr/bin/dbus-daemon --session --address=$DBUS_SESSION_BUS_ADDRESS --nofork --nopidfile --syslog-only &

        # --------------------
        # More background processes can be added here.
        # For 'sudo' requiring commands, you should add them above
        # where the 'dbus' service is started.
        # --------------------

    }
    fi
}

set_session_dbus





Add the following to your ~/.profile for loading ~/.bash_sysinit

if [ -f ~/.bash_sysinit ]; then
    . ~/.bash_sysinit
fi



You can either use ~/.profile or ~/.bashrc for adding the commands shown above. We recommend using ~/.profile since the default ~/.bashrc exits immediately if Bash was not invoked for an interactive session. The following post has more information about Bash login scripts.

Where should I add my DISPLAY environment variable?

Try opening a new Ubuntu/WSL2 console

Whenever a new Ubuntu console is opened, you should be able to confirm that DBUS_SESSION_BUS_ADDRESS environment variable is always pointing to the same Unix socket in your /run/user/$(id -u) directory.

Share This Story, Choose Your Platform!