Running notify-send as root
Asked Answered
I

8

28

I am trying to get a notification when pluging in a USB device, for this I use a udev rule to track the moment it is pluged and from there I launch a script. The idea on the script was to use what it is explained in the link.

but when trying this:

pids=`pgrep -u $user gnome-panel`

I found that gnome-panel is not there. Googled this work arround and I found quite few people complaining that this work arround is no longer working. So I did a bit of research on the subject and came up with this (notify-plugin2.sh):

#!/bin/bash

DBUS_SESSION_BUS_ADDRESS=$(cat /home/user/.dbus/session-bus/$(cat /var/lib/dbus/machine-id)-0 | grep DBUS_SESSION_BUS_ADDRESS= | sed -e 's/DBUS_SESSION_BUS_ADDRESS=//')

su user Test.sh $DBUS_SESSION_BUS_ADDRESS

to get the DBUS_SESSION_BUS_ADDRESS before switching user to a non root user. This statement, if I am not wrong works, so based on the code from the link above I made this other script (Test.sh)

#!/bin/sh
user=`whoami`
title="Test"
timeout=30000
icon="~/Pictures/PicturesForPwrPoint/Pluged.jpg"

DBUS_SESSION_BUS_ADDRESS=$1

echo $DBUS_SESSION_BUS_ADDRESS
DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS \ notify-send -u low -t $timeout -i "$icon" "$title"

For what I can see on the other code, the only problem was getting the DBUS_SESSION_BUS_ADDRESS, and if I am not wrong, with this I can have it.

So my question is, why there isn't a fancy pop-up message on my screen when launching?

sudo sh notify-plugin2.sh
Inoue answered 28/1, 2015 at 15:17 Comment(4)
it may be interesting to see the post in report bug section bugs.launchpad.net/ubuntu/+source/libnotify/+bug/160598Inoue
what is your operating system ?Documentation
ubuntu 14.04 LTS 32-bitInoue
See this answer for an example function which works in Ubuntu 16.04Quirk
G
38

Combining tomy's answer with hongo's answer to another question elegantly solves the issue for me.

function notify-send() {
    #Detect the name of the display in use
    local display=":$(ls /tmp/.X11-unix/* | sed 's#/tmp/.X11-unix/X##' | head -n 1)"

    #Detect the user using such display
    local user=$(who | grep '('$display')' | awk '{print $1}' | head -n 1)

    #Detect the id of the user
    local uid=$(id -u $user)

    sudo -u $user DISPLAY=$display DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$uid/bus notify-send "$@"
}

That function can be used as-is in any script running as root, as a drop-in replacement for the notify-send command.

Guggenheim answered 28/3, 2018 at 11:58 Comment(5)
Thanks. Saved me some time. Something similar to this for the last line could work. Tested on Debian 9: su - $user -c "DISPLAY=$display DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$uid/bus notify-send -i 'Title' 'Message'"Spyglass
@Spyglass the last line in the function is actually parameterized, see that "$@"? It allows you to pass the parameters -i 'Title' 'Message' directly to the function itself. It's meant to be used as a drop-in replacement for the real notify-send.Guggenheim
I'd update line 6 to include | head -n 1 ( Making it local user=$(who | grep '('$display')' | awk '{print $1} | head -n 1') ). I had it return 8 separate users on my machine :)Kesselring
On Fedora 35 the user= ... line did not work for me. This works for me and I think is more general (sorry I don't know how to get multiline code format in comment)... ``` bash function notify-send() { # find first X socket local socket=$(ls /tmp/.X11-unix/* | head -n 1) # extract display name, user, and user ID local display=":$(echo $socket | sed 's#/tmp/.X11-unix/X##')" local user uid read user uid <<< $(stat -c '%U %u' $socket) sudo -u $user DISPLAY=$display DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$uid/bus notify-send "$@" } ```Loralorain
For me on Arch Linux, this works (simplified, one-liner version of the solution in this answer): sudo -u "$USER" DISPLAY=":$(find /tmp/.X11-unix -type s | grep -Pom1 '/tmp/.X11-unix/X\K\d+$')" "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u "$USER")/bus" /usr/bin/notify-send 'Notification heading'.Accusal
C
18

To send desktop notification from a background script running as root
(replace X_user and X_userid with the user and userid running X respectively):

sudo -u X_user DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/X_userid/bus notify-send 'Hello world!' 'This is an example notification.'

This was taken from: https://wiki.archlinux.org/index.php/Desktop_notifications

Certified answered 22/3, 2018 at 11:1 Comment(1)
This one-liner was very handy, and used in combination with @hongo'sanswer to another question solves the issue for me.Guggenheim
D
9

The notification service has been changed for ubuntu 14.04.

Its called now smth like org.freedesktop.Notifications.service

You can check here for more information about Notification On Screen Display possibilities.

Also you can use following command line to send your own messages

user@machine ~$ notify-send “Text of message”

Just update your script which is being launched by udev to use it.


To workaround the problem realted to running the notify-send command as root.

Try to run is as your normal user, i.e.

su <YOURUSER> -c 'notify-send “Text of message”'
Documentation answered 29/1, 2015 at 12:56 Comment(4)
runing in the script the notify-send comand wont work because it will be executed as sudo notify-send thats the main problem. I am going to try this service name, I will update in a couple of minutesInoue
Ok, it seems I actually don't know what to do whit the service could you give me some indication on it?. And I can confirm that when running notify-send as root it won't show anythink, that was the whole point on the work arround I was talking about.Inoue
Update the answer with the suggestion how to workaround the root issue. Check it and come back in case there are quesitons.Documentation
It's nice to see I am not that lost, I already tried this one. Now I found this guy unix.stackexchange.com/questions/116536/… , thought he is using an other OS I tried this export DISPLAY=":0" but it didn't work eitherInoue
U
2
notify-send() 
{
    local display=$DISPLAY
    local user=$(who | grep '('$display')' | awk '{print $1}')
    local uid=$(id -u $user)
    sudo -u $user DISPLAY=$display DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$uid/bus notify-send "$@"
}

On the uos1022 system, I can query my own window through the environment variable $DISPLAY, so as to successfully pop up the notification bar as the root user

Unguentum answered 5/1, 2021 at 8:38 Comment(0)
L
2

I tried Fabio A's solution. However, I noticed that it was not working consistently on my Arch Linux installation. Problem was that who did not display the port number for the tty1 session:

$ who
john       tty1         2021-03-21 09:02

I am running i3 via exec startx on my Arch installation. On the other hand, I noticed that the output of who on a Ubuntu desktop installation looked completely different. Here, the display number is shown:

$ who
john       :0           2021-03-21 09:49 (:0)

So I was looking for another solution to get rid of the who command. I found that ps aux contains this useful entry which contains both the display number as well as the username:

$ ps aux | grep xinit
john 785 763 0 19:14 tty1 S+ 0:00 xinit /home/john/.xinitrc -- /etc/X11/xinit/xserverrc :0 vt1 -keeptty -auth /tmp/serverauth.gGcqw2rJXG

This is the new script I wrote:

#/bin/bash

xinit_pid=$(pgrep xinit)

if [ -n "xinit_pid" ]; then
    xinit_ps=$(ps --no-headers -f $xinit_pid | head -n 1)
    display=$(echo "$xinit_ps" | grep -Po " :[0-9]+ " | tr -d " ")
    user=$(echo "$xinit_ps" | cut -d " " -f 1)
    uid=$(id -u $user)
    echo "Display environment: $display $user $uid"
    sudo -u $user DISPLAY=$display DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$uid/bus notify-send "$@"
else
    echo "Warning: Could not find xinit process!"
fi

Any other script can call this script via:

bash /opt/notify-send-helper Title Message -t 5000

On a side note: I am using dunstify instead of notify-send. dunstify has the advantage of being able to assign IDs to a notification: Only the newest notification for the same ID is shown.

EDIT: I used to query the process "Xorg". However, strangely enough I noticed on one machine that this process was run as root. I switched to the "xinit" process instead which works just the same but seems to be always run by the normal user.

Lollar answered 19/3, 2021 at 21:21 Comment(0)
D
1

For me this much simpler method works:

dbus-launch notify-send "Header" "Message"
Dromond answered 6/6, 2022 at 12:38 Comment(0)
K
0

I also was looking into this to fix a bug with a corrupt background on restart. I wanted to add a script to /etc/pm/sleep.d/ to reset it but needed DBUS_SESSION_BUS_ADDRESS to set it (gnome desktop). I found that the DBUS_SESSION_BUS_ADDRESS stored in the /home/user/.dbus/session-bus/* files doesn't match the one in the users environment. But I did find that one available in one of the dbus-daemon commands.

So I was able to get DBUS_SESSION_BUS_ADDRESS via the snipped below and I was successfully able to use it. Replace "[username]" with your user. Hope this helps.

$ export DBUS_SESSION_BUS_ADDRESS=$(pgrep -a dbus-daemon -U [username] | grep -o 'unix:abstract.*$')
Karrikarrie answered 13/9, 2016 at 6:10 Comment(0)
L
0

I struggled with notify-send myself lateley and got it working (under Ubuntu 16.04).

I think there are 2 aspects. The calling user has to have access to the display, where the message shall be displayed and the display has to be specified.

root@mymachine~# who
root     tty1         2017-06-19 16:30
<user1>  tty7         2017-06-20 07:15 (:0)
<user1>  pts/2        2017-06-20 07:42 (:0.0)
root     pts/14       2017-06-20 07:05 (<IP1>)
<user1>  pts/16       2017-06-20 07:15 (:0.0)
root     pts/17       2017-06-19 17:15 (<IP2>)
<user2>               2017-06-20 07:39 (<IP3>:2) #VNC
<user1>  pts/26       2017-06-19 18:03 (<IP3>:1.0) #VNC

So what worked for me was

su - <user2> -c "DISPLAY=<IP3>:2 notify-send hi"

I think by switching to the user, you use their ~/.Xauthority. When authorized, specifying the display works.

I used another way to get the authority so far. I looped through the ~/.Xauthority files of every logged-in user and collected their authorizing cookies. Afterwards using the right DISPLAY-Variable works. I even collected the cookie of the display-manager (lightdm in my case)

The ~/.Xauthority-file (after collectiing):

root@mymaching:~# xauth list
<HOSTNAME3>:3  MIT-MAGIC-COOKIE-1  0ebdee59ee015f49066f372b00589420
<HOSTNAME3>:1  MIT-MAGIC-COOKIE-1  74254e326e8904419d005a05a6e95a8c
<HOSTNAME3>/unix:0  MIT-MAGIC-COOKIE-1  54d4cdb35eff20375e486f88e6ac8c74
<HOSTNAME3>:2  MIT-MAGIC-COOKIE-1  c6a07838c7456224799eedfff2be7cd5

My script so far (I guess it is not final yet)

#!/bin/bash
users="$(who | awk '{print $1}' | sort -u | grep -v root)"
rm ~/.Xauthority
touch ~/.Xauthority
for user in $users; do
   xauth_file=/home/$user/.Xauthority
   while read cookie; do
      xauth add $cookie
   done <<< "$(xauth -f $xauth_file  list | grep $HOSTNAME)"
done
for xauth_file in $(find /var/run/lightdm -type f); do
   while read cookie; do
      xauth add $cookie
   done <<< "$(xauth -f $xauth_file  list | grep $HOSTNAME)"
done
for display in $(xauth list | awk '{print $1}' | cut -d/ -f2); do
   DISPLAY=$display notify-send "$@"
done

Legend: Items in <> are anonymised. IPX matches HOSTNAMEX

Greetings dasBaschdi

Liebman answered 20/6, 2017 at 6:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.