How to send a message to running X Windows sessions in a multi-user Linux system
June 2, 2020 Leave a comment
The ‘wall
‘ command can be used to broadcast a message from a TTY console to other logged-in TTY console users in a multi-user Linux system. The Linux command ‘notify-send
‘ can be used to send a message (a.k.a. notification) within an X Windows session, and Desktop Environments such as KDE and GNOME use notify-send
to display pop-up notifications to the user. However, apparently no program exists in Linux to broadcast a message to other running X Windows sessions; that sounds like the sort of thing systemd developers would implement. A few years ago Unix & Linux Stack Exchange user Andy posted a Bash script notify-send-all
to do just that (see Show a notification across all running X displays). For example, if you wanted to send a message to all the users of a multi-seat, multi-user Linux system who are currently logged-in to Desktop Environments, you could enter the following command to run the script in your home directory:
$ sudo ./notify-send-all -t 50000 "Warning" "Don't forget the staff meeting at 15:00 today."
Below is a slightly modified version of Andy‘s script that works for me in Lubuntu 18.04:
#!/bin/bash PATH=/usr/bin:/bin who|grep -E "\(:[0-9](\.[0-9])*\)"|awk '{print $1$5}'|sort -u > /tmp/xusers while read XUSER; do NAME=(${XUSER/(/ }) DISPLAY=${NAME[1]/)/} DBUS_ADDRESS=unix:path=/run/user/$(id -u ${NAME[0]})/bus sudo -u ${NAME[0]} DISPLAY=${DISPLAY} \ DBUS_SESSION_BUS_ADDRESS=${DBUS_ADDRESS} \ PATH=${PATH} \ notify-send "$@" done < /tmp/xusers
Here is my tidied-up version:
#!/bin/bash who | awk '{print $1, $NF}' | tr -d "()" | sort -u | while read XUSER DISPNUM; do sudo -u $XUSER DISPLAY=$DISPNUM \ DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u $XUSER)/bus \ notify-send "$@" done
In Gentoo Linux DBUS_SESSION_BUS_ADDRESS
needs to be found differently, and the following version of Andy‘s script works for me in that Linux distribution:
#!/bin/bash PATH=/usr/bin:/bin export $(dbus-launch) who|grep -E "\(:[0-9](\.[0-9])*\)"|awk '{print $1$5}'|sort -u > /tmp/xusers while read XUSER; do NAME=(${XUSER/(/ }) DISPLAY=${NAME[1]/)/} sudo -u ${NAME[0]} DISPLAY=${DISPLAY} \ ${DBUS_SESSION_BUS_ADDRESS} \ PATH=${PATH} \ notify-send "$@" done < /tmp/xusers
And here is my tidied-up version:
#!/bin/bash export $(dbus-launch) who | awk '{print $1, $NF}' | tr -d "()" | sort -u | while read XUSER DISPNUM; do sudo -u $XUSER DISPLAY=$DISPNUM \ $BUS_SESSION_BUS_ADDRESS \ notify-send "$@" done
notify-send-all
will be of academic interest to users of single-user systems, but it’s nice to know such a thing is possible relatively easily in Linux.