6
#!/bin/bash
export DISPLAY=:0
state=$(upower -i $(upower -e | grep BAT) | grep --color=never -E "state" )
stat=${state:25:32}
batperct=$(upower -i $(upower -e | grep '/battery') | grep  -E "percentage:")
bat=${batperct:24:26}
intbat=$(echo $bat | cut -d'%' -f1)
if [ "$intbat" -lt "15" -a "$stat" == "discharging" ]; then
    notify-send 'battery low..! please plugin charger..... charge is only' "$intbat"    
fi  

The script runs fine when run as a normal user (bash script.sh). The desktop notification is displayed.

If I run it as root with sudo bash script.sh, the desktop notification is not displayed.

How can I use notify-send to notify users as root?

I am using Arch Linux.

Ralf
  • 507
  • 2
  • 10
  • 2
    Please show how you are running the script. – l0b0 Jan 05 '19 at 08:02
  • like when run script like bash script.sh it runs but when i use sudo and run it doesnt – Prinz Piuz Jan 05 '19 at 10:31
  • 2
    by "it doesn't" do you mean it "doesn't run and I get a sudo error", or "it doesn't run and emits THIS error" or what? – Jeff Schaller Jan 05 '19 at 12:32
  • 1
    did you keep $XAUTHORITY when becoming root? – A.B Jan 05 '19 at 13:36
  • Why would you want to run this as root? It's supposed to notify your user, right? Root can't connect to the X server you'r running, which is why it doesn't work, but really why would you want this to be run s root? – terdon Jan 05 '19 at 17:37
  • @PrinzPiuz I would propose to change the question to "How to use notify-send to notify users as root?" – Ralf Jan 05 '19 at 18:51
  • @terdon i was trying to run it as deamon but it get exit with error 127 ..i think deamon run script with root privilege..so i tried to run it as root – Prinz Piuz Jan 06 '19 at 03:37

1 Answers1

4

The command notify-send needs the environment variable DBUS_SESSION_BUS_ADDRESS set and must be called with the owner of this session bus as user.

In the following script the function notify_users searches for all dbus-daemons that control a session bus. The command line of such a daemon looks like this:

dbus-daemon --fork --session --address=unix:abstract=/tmp/dbus-ceVHx19Kiy

For this processes the owner and the dbus address is determined. Then we are able to use notify-send. This script should inform all user logged in with a GDM session. But I never tested that.

Note: If you call this as non-root, you might get queried for a password due to the use of sudo.

#!/bin/bash

# Inform all logged on users
# Usage: notify_users TITLE MESSAGE [urgency [icon]]
notify_users()
{
    typeset title="$1"
    typeset message="$2"
    typeset urgency="${3:-critical}"
    typeset icon="${4:-}"

    case "$urgency" in
        "low") : ;;
        "normal") : ;;
        "critical") : ;;
        *)
            urgency="normal"
            ;;
    esac

    typeset ls user bus_addr

    typeset IFS=$'\n'

    # for all dbus-daemon processes that create a session bus
    for ln in "$(ps -eo user,args | grep "dbus-daemon.*--session.*--address=" | grep -v grep)"; do
        # get the user name
        user="$(echo "$ln" | cut -d' ' -f 1)"
        # get dbus address
        bus_addr="$(echo "$ln" | sed 's/^.*--address=//;s/ .*$//')"
        # run notify-send with the correct user
        DBUS_SESSION_BUS_ADDRESS="$bus_addr" sudo -u $user -E /usr/bin/notify-send -u "$urgency" -i "$icon" "$title" "$message"
    done
}

state="$(upower -i $(upower -e | grep BAT))"

# if the state contains the word "discharging"
if [[ "$state" = *discharging* ]]; then

    perc=$(echo "$state" | grep "percentage" | awk '{print $2}' | tr -d '%')

    icon="$(echo "$state" | grep "icon-name:" | awk '{print $2}' | tr -d "'\"" )"

    if [ "$perc" -lt 15 ]; then
        notify_users "Battery Low!"  "Please plugin charger ... charge is only $perc%" "critical" "$icon"
    fi
fi
Ralf
  • 507
  • 2
  • 10
  • what my i aim is to run my script as system deamon this is my .service file [Unit] Description=Battery Indicator [Service] ExecStart=/bin/bash /home/prinzpiuz/GitHub/myScripts/shell/bat Restart=on-failure [Install] WantedBy=multi-user.target but i am getting error like (code=exited, status=127) – Prinz Piuz Jan 06 '19 at 03:49
  • First: 127 means "command not found". Second: This script is no daemon, so it makes no sense to start it as a service. It might be used to be started as a cronjob, say every 5 minutes. Third: You should create a separate question. Last: See here and here. – Ralf Jan 06 '19 at 08:33