There are several methods that can be used for text message exchanging between different non-privileged users. Usually, when the sender of such a message is a service and the recipient, who is supposed to see the message, is a human, that message is called a “notification“. The method used by many services that run within the scope of a desktop session in order to send notifications to the desktop session owners involves the use of DBus and libnotify. But, would it be possible to use libnotify to send notification messages from a system service to one or more desktop users?
Despite my last post’s overwhelming optimism, it is sometimes impossible to find a solution for a problem, because one does not exist. It turns out that the above task cannot be accomplished, at least at the moment of writing, as it is impossible for one user (system account or other non-privileged user) to send a notification through libnotify to another user that runs a desktop session. The easiest way to test this is with a cron job in the system’s crontab:
*/1 * * * * root /usr/bin/notify-send "lala" "test message"
No notification appears on the desktop, no matter how long I wait. After doing some research it turns out that notify-send cannot automatically send notifications to all users that run a desktop session. It can only send notifications only to one user at a time provided that the user’s D-Bus session address is available to notify-send
.
So, I decided to set the cron job to send a notification to my own user account by providing notify-send with my DBUS_SESSION_BUS_ADDRESS.
The following is a method a system user (or any user except me) would use to retrieve my DBUS_SESSION_BUS_ADDRESS address. These steps are actually taken from this GNOME-Hack, which is supposed to send notifications from a cronjob.
In order to retrieve this address, my gnome-session’s PID number is needed.
$ ps axu | grep gnome-session | grep -v grep gnot 2602 0.0 1.3 33432 7064 ? Ssl 16:56 0:00 /usr/bin/gnome-session
The needed PID number is 2602. The D-BUS session’s address exists as an environment variable (DBUS_SESSION_BUS_ADDRESS) of that process (2602). This can be retrieved with the following:
$ grep -z DBUS_SESSION_BUS_ADDRESS /proc/2602/environ DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-vKzOHyaDdi,guid=f45436454463d8df2f8d265447405220
Notice that the PID number has been used in the /proc/2602/environ
path.
Adding this information to the initial cronjob one would expect that the notification would appear on the desktop.
*/1 * * * * root DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-vKzOHyaDdi,guid=f45436454463d8df2f8d265447405220 /usr/bin/notify-send "lala" "test message"
Unfortunately, it didn’t. I also retrieved my desktop session’s display number and added it to the cron job.
*/1 * * * * root DISPLAY=:0.0 DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-vKzOHyaDdi,guid=f45436454463d8df2f8d265447405220 /usr/bin/notify-send "lala" "test message"
Unfortunately, nothing happened.
It seems that not only notify-send
can send a notification to only one desktop session owner at a time, but also it is that desktop session owner who must issue the notify-send
command. So, as long as most system services drop privileges and run as processes of non-privileged system users, they cannot send notifications to desktop users.
This is probably because of one or more of the following reasons:
- either D-Bus is incomplete when it comes to message exchanging between non-privileged users
- or there is some kind of security mechanism that prevents the above from happening. Unfortunately, I haven’t found any information about such a mechanism.
- or I miss something way too important.
- or I make a mistake in one of the steps.
If I miss anything, please let me know.
Problems using libnotify for User to User Notifications by George Notaras is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Copyright © 2007 - Some Rights Reserved
You also need an user that runs X. I do it via script http://gnome-hacks.org/hacks.html?id=82 plus get user name from same source:
Hi Aleksei, thanks for this tip. Using sudo should work, but I am not able to test it right now. I’ll post any good news :)
Henning, please make sure you leave a link to that blog post here in the comments when it’s published, so other readers can easily locate it. Thanks for your work! :)
Hi,
This post is not that new, but newsworthy and in some parts unsolved anyway…
I wrote a small script to be used to send a broadcast-message via notify-send. It should have been quite easy, but I could not find any ready-to-use-stuff on google, so i wrote it by myself.
Henning
Thanks you for this information. I could thus built a script to automate my need to report some kind of system messages to user based on their UID. May this be useful to anyone wanting to branch certain syslog-ng messages (messages corresponding to output network packets dropped by netfilter, have the UID field in them) to the corresponding user.
Regards,
Edrusb.
#!/bin/sh
if [ -z "$1" -o -z "$2" ] ; then
echo "usage: $0 "
exit 1
fi
UID="$1"
MESSAGE="$2"
#DEBUG=no
DEBUG=yes
####################################################
# looking for user name from UID
USERNAME=`cut -f 1,3 -d ':' /etc/passwd | grep ":$1" | cut -f 1 -d ':'`
if [ "$DEBUG" = "yes" ] ; then
echo "username = $USERNAME"
fi
####################################################
# looking for the session process
LEADER=`ps -e -o pid,user,comm | grep gnome-session | grep "$USERNAME" | sed -r -e 's/\s+/ /g' -e 's/^\s+//' | cut -f 1 -d ' '`
if [ "$DEBUG" = "yes" ] ; then
echo "leader = $LEADER"
fi
if [ -z "$LEADER" ] ; then
echo "user = $USERNAME\nUID = $UID\nmessage = $MESSAGE" | mail -s "user absent for notification !" root
exit 0
fi
####################################################
# fetching environnement variables
VARIABLES=`egrep -z 'DBUS_SESSION_BUS_ADDRESS|DISPLAY' /proc/$LEADER/environ | sed -r -e 's/(.)DBUS_/\1 DBUS_/' -e 's/(.)DISPLAY/\1 DISPLAY/'`
if [ "$DEBUG" = "yes" ] ; then
echo "variables = $VARIABLES"
fi
####################################################
# final !
su $USERNAME -s /bin/sh -c "$VARIABLES notify-send -t 2000 -u critical 'Attention !' '""$MESSAGE""'"
well, the “greater than” “lower than” symbols have been dropped in the copy/past . So you can replace line 4 of the script by :
echo “usage: $0 [UID] [message]”