it-swarm-es.tech

Mostrar una notificación en todas las pantallas X en ejecución

Usando la línea de comando, me gustaría mostrar una notificación en cada pantalla X en ejecución. (y consola en ejecución)

Algo como:

notify-send-all 'Warning' 'Nuclear launch in 5 minutes, please evacuate'

¿Existe algún programa que haga esto? Si no es así, ¿se puede implementar con bash?

16
Stefan

Puede enviar un mensaje a todas las consolas con el muro de comandos.

Para enviar notificaciones bajo X, hay una notificación-envío que envía una notificación al usuario actual en la pantalla actual. (Por tu pregunta, supongo que ya conoces esta.) Puedes construir sobre esto con algunas secuencias de comandos bash. Básicamente, debe averiguar qué usuarios están en qué X-Displays. Una vez que obtenga esta información, puede usar notificar-enviar de esta manera:

DISPLAY=:0 Sudo -u fschmitt notify-send "Message"

Donde fschmitt es el usuario en la pantalla 0. Puede analizar la salida del comando "who" para encontrar todos los usuarios y sus pantallas. La salida se ve así

[edinburgh:~]$ who
markmerk3 tty7         2010-09-23 10:59 (:0)
markmerk3 pts/1        2010-09-30 13:30 (:0.0)
fschmitt pts/2        2010-10-08 11:44 (ip-77-25-137-234.web.vodafone.de)
markmerk3 pts/0        2010-09-29 18:51 (:0.0)
seamonkey pts/6        2010-09-27 15:50 (:1.0)
markmerk3 pts/5        2010-09-27 14:04 (:0.0)
seamonkey tty8         2010-09-27 15:49 (:1)
markmerk3 pts/13       2010-09-28 17:23 (:0.0)
markmerk3 pts/3        2010-10-05 10:40 (:0.0)

Verá, hay dos usuarios ejecutando sesiones X, markmerk3 en la pantalla 0 y seamonkey en la pantalla 1. Creo que necesita grep para tty [0-9] * y luego asegurarse de que al final de la línea haya (: [0 -9.] *) Para deshacerse de los inicios de sesión de la consola y extraer la identificación de pantalla de la cadena entre paréntesis.

16
fschmitt

Este hilo es un poco antiguo, lo siento, pero espero poder agregar algo útil al tema. (también Josef Kufner escribió un buen script, era un poco demasiado largo para mi gusto y usa PHP)

También necesitaba una herramienta como se describe en la pregunta original (para enviar un mensaje a todos los usuarios X activos). Y en base a las respuestas aquí, escribí este pequeño script solo de bash, que busca usuarios X activos (usando 'quién') y luego ejecuta notificar-enviar para cada usuario activo.

Y lo mejor: puedes usar mi script exactamente como "notificar-enviar", ¡con todos sus parámetros! ;-)

notificar-enviar-todo:

#!/bin/bash
PATH=/usr/bin:/bin

XUSERS=($(who|grep -E "\(:[0-9](\.[0-9])*\)"|awk '{print $1$5}'|sort -u))
for XUSER in $XUSERS; 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 "[email protected]"
done

Copie el código anterior en un archivo llamado "notificar-enviar-todo", hacerlo ejecutable y copiarlo en / usr/local/bin o / usr/bin (como te gusta). Luego ejecútelo, p. Ej. como root en una sesión de consola como esta:

notify-send-all -t 10000 "Warning" "The hovercraft is full of eels!"

Lo estoy usando desde hace varios meses, en diferentes máquinas, y no he tenido ningún problema hasta ahora, y lo he probado con MATE y Cinnamon desktops. También ejecutándolo exitosamente dentro de cron y anacron.

Escribí este script para/bajo ArchLinux, así que por favor dígame si tiene problemas con otras distribuciones o escritorios de Linux.

10
Andy

En Ubuntu 16.04, quería notificaciones de un script que se ejecutaba como root desde crontab. Después de configurar las variables de entorno, Sudo -u $user no funcionó por alguna razón, pero sh -c "..." $user funciona.

Entonces ahora uso esta función:

notify_all() {
    local title=$1
    local msg=$2

    who | awk '{print $1, $NF}' | tr -d "()" |
    while read u d; do
        id=$(id -u $u)
        . /run/user/$id/dbus-session
        export DBUS_SESSION_BUS_ADDRESS
        export DISPLAY=$d
        su $u -c "/usr/bin/notify-send '$title' '$msg'"
    done 
}

La forma de encontrar la variable DBUS_SESSION_BUS_ADDRESS probablemente depende de su distribución. En Ubuntu 16.04, está en /run/user/$UID/dbus-session, que simplemente se puede obtener. id -u se utiliza en la función anterior para obtener el UID del nombre de usuario devuelto por who.

3
mivk

También lo necesitaba para algunas notificaciones de todo el sistema. Aquí está mi solución. Escanea/proc para encontrar todos los buses de sesión y luego ejecuta el envío de notificación en cada uno de ellos (una vez por bus). Todos los argumentos se pasan sin cambios al envío de notificación real.

#!/bin/bash

/bin/grep -sozZe '^DBUS_SESSION_BUS_ADDRESS=[a-zA-Z0-9:=,/-]*$' /proc/*/environ \
| /usr/bin/php -r '
        $busses = array();
        array_shift($argv);
        while($ln = fgets(STDIN)) {
                list($f, $env) = explode("\0", $ln, 2);
                if (file_exists($f)) {
                        $user = fileowner($f);
                        $busses[$user][trim($env)] = true;
                }
        }
        foreach ($busses as $user => $user_busses) {
                foreach ($user_busses as $env => $true) {
                        if (pcntl_fork()) {
                                posix_seteuid($user);
                                $env_array = array("DBUS_SESSION_BUS_ADDRESS" => preg_replace("/^DBUS_SESSION_BUS_ADDRESS=/", "", $env));
                                pcntl_exec("/usr/bin/notify-send", $argv, $env_array);
                        }
                }
        }
' -- "[email protected]"
3
Josef Kufner

Aquí hay una actualización del guión de Andy: La forma en que determinó el DBUS_SESSION_BUS_ADDRESS no funciona en Centos 7. Además, el comando who no enumeraba algunas sesiones por alguna razón, así que analizo el ps aux salida en su lugar. Este script asume que los usuarios están conectados usando X2GO (nxagent), pero debería ser fácil de ajustar para otros casos.

#!/bin/bash
PATH=/usr/bin:/bin
NOTIFY_ARGS='-u critical "Shutdown notice" "THE SYSTEM IS GOING DOWN TODAY AT 23:00.\nWe recommend you to save your work in time\!" -i /usr/share/icons/Adwaita/32x32/devices/computer.png -t 28800000'

function extract_displays {
    local processes=$1
    processes=$(printf '%s\n' "$processes" | grep -P "nxagent.+:\d+")
    ids=$(printf '%s\n' "$processes" | grep -oP "\W\K:(\d)+")
    echo $ids
}


function find_dbus_address {
    local name=$1
    PID=$(pgrep 'mate-session' -u $name)
    if [ -z "$PID" ]; then
        PID=$(pgrep 'gnome-session' -u $name)
    fi
    if [ -z "$PID" ]; then
        PID=$(pgrep 'xfce4-session' -u $name)
    fi

    exp=$(cat /proc/$PID/environ | grep -z "^DBUS_SESSION_BUS_ADDRESS=")
    echo $exp
}

PROCESSES=$(ps aux)
DISPLAY_IDS=$(extract_displays "$PROCESSES")
echo "Found the following DISPLAYS: $DISPLAY_IDS"
for DISPLAY in $DISPLAY_IDS; do
    NAME=$(printf '%s\n' "$PROCESSES" | grep -P "nxagent.+$DISPLAY" | cut -f1 -d ' ')
    DBUS_ADDRESS=$(find_dbus_address $NAME)
    echo "Sending message to NAME=$NAME DISPLAY=$DISPLAY DBUS_ADDRESS=$DBUS_ADDRESS"
    echo "NOTIFY_ARGS=$NOTIFY_ARGS"
    eval Sudo -u ${NAME} DISPLAY=${DISPLAY} ${DBUS_ADDRESS} PATH=${PATH} notify-send $NOTIFY_ARGS
done
0
jpf