Usando send-send con cron

32

Estoy usando Arch Linux con KDE / Awesome WM. Estoy tratando de ponerme notify-senda trabajar cron.

He intentado establecer DISPLAY/ XAUTHORITYvariables y ejecutar notify-sendcon "sudo -u", todo sin resultado.

Puedo llamar a notificar-enviar interactivamente desde la sesión y recibir notificaciones.

FWIW, el trabajo cron está funcionando bien, lo cual verifiqué haciendo eco de cosas en un archivo temporal. Es solo el "notificar-enviar" que no funciona.

Código:

[matrix@morpheus ~]$ crontab -l
* * * * *  /home/matrix/scripts/notify.sh

[matrix@morpheus ~]$ cat /home/matrix/scripts/notify.sh
#!/bin/bash
export DISPLAY=127.0.0.1:0.0
export XAUTHORITY=/home/matrix/.Xauthority
echo "testing cron" >/tmp/crontest
sudo -u matrix /usr/bin/notify-send "hello"
echo "now tested notify-send" >>/tmp/crontest

[matrix@morpheus ~]$ cat /tmp/crontest
testing cron
now tested notify-send

[matrix@morpheus ~]$ 

Como puede ver, el eco antes y después de notificar-enviar funcionó.
También he intentado configurarDISPLAY=:0.0

ACTUALIZACIÓN: Busqué un poco más y descubrí que DBUS_SESSION_BUS_ADDRESS debe establecerse. ¡Y después de codificar esto usando el valor que obtuve de mi sesión interactiva, el pequeño mensaje de "hola" comenzó a aparecer en la pantalla cada minuto!

Pero el problema es que esta variable no es permanente por esa publicación, por lo que tendré que probar la solución de tubería con nombre sugerida allí.

[matrix@morpheus ~]$ cat scripts/notify.sh
#!/bin/bash
export DISPLAY=127.0.0.1:0.0
export XAUTHORITY=/home/matrix/.Xauthority
export DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-BouFPQKgqg,guid=64b483d7678f2196e780849752e67d3c
echo "testing cron" >/tmp/crontest
/usr/bin/notify-send "hello"
echo "now tested notify-send" >>/tmp/crontest

Dado cronque no parece admitir notificación-envío (al menos no directamente), ¿hay algún otro sistema de notificación que sea más cronamigable que pueda usar?

solo alguien
fuente
Esto debería funcionar hasta donde puedo ver. ¿Por qué no agrega un &>>/tmp/crontesta la línea de envío de notificaciones y ve si notify-sendda algún mensaje de error?
Graeme
Por curiosidad, ¿probaste mi solución? Parece mucho más simple y funcionó perfectamente en mi Debian. Solo pregunto si es específico de Debian o no
terdon
@terdon Probé su solución (solo una prueba rápida) y parece funcionar en mi sistema Debian. Me gustaría saber si es generalmente aplicable, ya que de hecho es más simple.
Marco
@Marco Estoy en LMDE (esencialmente pruebas de Debian) y estoy usando Cinnamon como DE. No puedo decirte si funciona más allá de eso.
terdon
@Marco & terdon: los chicos de Ubuntu pueden hacerlo: ubuntuforums.org/showthread.php?t=1727148
justsomeone

Respuestas:

29

Necesitas establecer la DBUS_SESSION_BUS_ADDRESSvariable. Por defecto, cron no tiene acceso a la variable. Para remediar esto, coloque el siguiente script en algún lugar y llámelo cuando el usuario inicie sesión, por ejemplo, utilizando awesome y la run_oncefunción mencionada en la wiki. Cualquier método funcionará, ya que no hace daño si la función se llama con más frecuencia de la requerida.

#!/bin/sh

touch $HOME/.dbus/Xdbus
chmod 600 $HOME/.dbus/Xdbus
env | grep DBUS_SESSION_BUS_ADDRESS > $HOME/.dbus/Xdbus
echo 'export DBUS_SESSION_BUS_ADDRESS' >> $HOME/.dbus/Xdbus

exit 0

Esto crea un archivo que contiene la variable de entorno Dbus requerida. Luego, en el script llamado por cron, importa la variable obteniendo el script:

if [ -r "$HOME/.dbus/Xdbus" ]; then
  . "$HOME/.dbus/Xdbus"
fi

Aquí hay una respuesta que usa el mismo mecanismo.

Marco
fuente
1
Me alegra ver que estaba casi cerca de la solución. Gracias Marco, eso es genial!
Justsomeone
Genial, reutilicé su respuesta y agregué algunas instrucciones más detalladas aquí: askubuntu.com/a/537721/34298
rubo77
¿No sería esto un riesgo de seguridad? security.stackexchange.com/questions/71019/…
rubo77
@Gilles ¿Cómo podrías hacer esto en una línea como mencionaste en el chat?
rubo77
He intentado muchas otras respuestas sin incluir DBUS en ubuntu 15.10 y nada funcionó. Ese es simple y funciona perfectamente.
bastian
16

Debe configurar las variables en el crontab mismo:

DISPLAY=:0.0
XAUTHORITY=/home/matrix/.Xauthority

# m h  dom mon dow   command 
* * * * *  /usr/bin/notify-send "hello"

No es sudonecesario, al menos no en mi sistema.

terdon
fuente
Gracias terdon por tu tiempo. Esto parece ser una solución simple. Por desgracia, esto no funcionó para mí,
justsomeone
@justsomeone eh, OK, entonces podría depender del entorno de escritorio.
terdon
Creo que esto tiene algo que ver con distro o Desktop Environment. Para los usuarios de Ubuntu, las soluciones directas parecen funcionar bien de lo que he visto en los foros en línea.
Justsomeone
@justsomeone Estoy en Debian (LMDE) usando Cinnamon como DE. Podría tener algo que ver con cómo se inicia X o con el sistema de notificaciones utilizado por el DE, no lo sé.
terdon
Confirmó que funciona en Ubuntu 14.04 / 14.10. Con GNOME y Unity.
Jordon Bedwell
8

La forma más segura de obtener variables ambientales relacionadas con la sesión X es obtenerlas del entorno de un proceso del usuario que ha iniciado sesión en X. Aquí hay una adaptación del script que uso exactamente para el mismo propósito (aunque DBUS_SESSION_BUS_ADDRESS no No parece ser un problema para mí en Debian):

X=Xorg                   # works for the given X command
copy_envs="DISPLAY XAUTHORITY DBUS_SESSION_BUS_ADDRESS"

tty=$(ps h -o tty -C $X | head -1)
[ -z "$tty" ] && exit 1

# calling who with LANG empty ensures a consistent date format
who_line=$(LANG= who -u | grep "^[^ ]\+[ ]\+$tty")

x_user=$(echo $who_line | cut -d ' ' -f 1)  # the user associated with the tty
pid=$(echo $who_line | cut -d ' ' -f 7)     # the user's logon process

for env_name in $copy_envs
do
  # if the variable is not set in the process environment, ensure it does not remain exported here
  unset "$env_name"

  # use the same line as is in the environ file to export the variable
  export "$(grep -az "^$env_name=" /proc/$pid/environ)" >/dev/null
done

sudo -u "$x_user" notify-send "hello"

Esto envía un mensaje al primer usuario X que encuentra, aunque puede agregar un bucle para enviarlo a todos los usuarios.

Actualizar

Parece que las actualizaciones al formato utmp hacen whoque se imprima una pantalla en lugar de un tty en su segunda columna. Esto realmente facilita las cosas, anteriormente solo imprimía la pantalla en el comentario al final y decidí que no era seguro confiar en la respuesta original. Si este es el caso, intente esto:

X=Xorg                   # works for the given X command
copy_envs="DISPLAY XAUTHORITY DBUS_SESSION_BUS_ADDRESS"

# calling who with LANG empty ensures a consistent date format
who_line=$(LANG= who -u | awk '$2 ~ ":[0-9]"')

x_user=$(echo $who_line | cut -d ' ' -f 1)  # the user associated with the tty
pid=$(echo $who_line | cut -d ' ' -f 7)     # the user's logon process

for env_name in $copy_envs
do
  # if the variable is not set in the process environment, ensure it does not remain exported here
  unset "$env_name"

  # use the same line as is in the environ file to export the variable
  export "$(grep -az "^$env_name=" /proc/$pid/environ)" >/dev/null
done

sudo -u "$x_user" notify-send "hello"
Graeme
fuente
Esto no funciona para mí en Trusty porque no hay tty impreso en el who_linecomando. La salida se ve así me :0 2015-09-23 10:40 ? 17234.
Blujay
1
@blujay, actualizado.
Graeme
Gracias, eso funciona. Sin embargo, como publiqué en una respuesta por separado, hay una solución aún más simple.
Blujay
@ Blujay, sí, este fue un intento de una respuesta portátil. Sin embargo, no estoy seguro de que esto sea realmente posible, pero aún debería funcionar en la mayoría de los casos.
Graeme
2

Esta frase me funcionó en Manjaro con Cronie:

# Note: "1000" would be your user id, the output of... "id -u <username>" 
10 * * * * pj DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus notify-send 'Hello world!' 'This is an example notification.'

Sin el muy feo DBUS_blah_blah no funciona en absoluto. También me pareció journalctl -xb -u cronieútil. Todavía no estoy familiarizado con Cronie, pero creé mi "crontab" como /etc/cron.d/mycronjobsy no estoy seguro de si ese nombre de archivo es obligatorio, o si solo lee todo en el directorio cron.d.

Encontré la solución aquí https://wiki.archlinux.org/index.php/Desktop_notifications

PJ Brunet
fuente
2

Yo uso i3 en Ubuntu 18.04. Mi forma de resolver esto es:

* * * * * XDG_RUNTIME_DIR=/run/user/$(id -u) notify-send Hey "this is dog!"

Señor goferito
fuente
1

Esto es suficiente para hacer que el envío de notificaciones funcione para mí en un trabajo cron en Ubuntu Trusty:

#!/bin/bash
export DISPLAY=$(who -u | awk  '/\s:[0-9]\s/ {print $2}')

Simplemente exporta DISPLAYpara el usuario como se está ejecutando el cronjob. Funciona para mí sin configurar XAUTHORITYoDBUS_SESSION_BUS_ADDRESS .

Blujay
fuente
1
Funciona en Ubuntu 16.04 también. De hecho, tengo cron iniciando un script Perl, cuyo sistema () es un script bash, que inicia un script Perl diferente, que realiza un sistema ("notificar-enviar ..."). Agregar el comando de exportación al script bash modificó el entorno para ese script, que el último script de Perl luego heredó y puso a disposición del sistema ("notificar-enviar ..."). Buen hallazgo blujay!
Tim
1

Para aquellos en Linux que se sienten cómodos instalando paquetes de Python, acabo de lanzar un programa de notificación sin envío que funciona bien para mí. Busca /procel nombre de usuario requerido y las variables de entorno y luego se ejecuta notify-sendcon estas variables (se usará sudopara cambiar al usuario requerido si es necesario).

xolox
fuente
1

También puedes hacer un script:

#!/usr/bin/env bash
runuser -l [yourusername] -c 'DISPLAY=:0 notify-send "hey there user"'

Luego ejecútalo con sudo. Sin embargo, dado que crontab -eejecuta todos los comandos con el usuario que lo creó, lo siguiente debería ser suficiente cuando se llama sin sudo:

#!/usr/bin/env bash
DISPLAY=:0 notify-send "hey there user"

Por lo menos lo hace por mí. Todo parece depender de la configuración del entorno.

usuario1112789
fuente
0

Utilizo este script en cron para publicar MPD ahora jugando en twitter cada hora

#!/bin/bash
export DISPLAY=":0.0"
msg=$(mpc current -h 192.168.1.33)
twitter set "#MPD Server nowplaying $msg :  http://cirrus.turtil.net:9001"
#ttytter -status="#MPD Server nowplaying $msg. http://cirrus.turtil.net:9001"

exit 

secuencia de comandos similar que utiliza notificar-enviar

#!/bin/bash
export DISPLAY=":0.0"
notify-send -i ~/.icons/48arch.png 'OS- Archlinux x86_64 : DWM Window Manager' 'Installed on Sun Apr 21 2013 at 18:17:22' 
exit

puede estar experimentando problemas ya que KDE usa su propio notificar-deamon IIRC

cirro
fuente
0

Por lo que vale....

Tuve que usar TODO lo siguiente en Debian Jessie para que esto funcione ...

export DISPLAY=:0.0
export HOME=/home/$user
source "$HOME/.dbus/session-bus/*-0"

Dejar de lado alguno de estos hizo que dejara de funcionar.

BenJ
fuente
Esa última línea no hará nada como está escrito aquí, porque no habrá ningún archivo llamado literalmente *-0en su session-busdirectorio. Podrías haber querido decir source "$HOME"/.dbus/session-bus/*-0.
roaima 05 de
0

Usando sudo:

sudo -u $currentxuser notify-send $message

Propina :

Podemos obtener el usuario x actual con este comando

ps auxw | grep -i screen | grep -v grep | cut -f 1 -d ' '

Adicionalmente...

currentxuser=$(ps auxw | grep -i screen | grep -v grep | cut -f 1 -d ' ')
echo $currentxuser

Bueno saber :

Cron que se ejecuta bajo root no tiene acceso a x, por lo tanto, no se mostrarán todos los comandos de interfaz gráfica de usuario, una solución simple es agregar root al usuario x autorizado para el usuario x actual con este comando

del usuario x shell

xhost local:root

o

sudo -u $currentxuser xhost local:root
intika
fuente
-1

Aquí hay un script menos complejo que el que Graeme proporcionó. Su guión no funcionó para mí, $who_linesiempre estaba vacío. Mi guión no pierde tanto tiempo en encontrar un proceso. En cambio, solo intenta todo y elige el último valor útil encontrado. Estoy ejecutando xubuntu 14.04 y tengo algunos contenedores lxc en ejecución que probablemente confunden este tipo de scripts.

env="$(
  ps -C init -o uid,pid | while read u p; do
    [ "$u" = "`id -u`" ] || continue
    grep -az '^DBUS_SESSION_BUS_ADDRESS=' /proc/$p/environ | xargs -0
  done | tail -1
)"

export "$env"

notify-send "test"
Daniel Alder
fuente
Esto no funciona para mí en Trusty porque el entorno del proceso Xorg no tiene DBUS_SESSION_BUS_ADDRESS. Puedo obtenerlo de mis proyectiles, pero no del proceso Xorg.
Blujay