Notify-send no funciona desde crontab

44

Hice un guión que debería notificarme cuando hay un nuevo capítulo de manga que estoy leyendo. Usé el comando notify-send para hacer esto. El programa funciona cuando intento ejecutarlo en la terminal. La notificación se muestra. Sin embargo, cuando coloqué esto en mi crontab, la notificación no se muestra. Estoy bastante seguro de que el programa se está ejecutando, ya que lo hice para crear un archivo para mí. El archivo fue creado, pero la notificación no se mostró.

Aquí está mi guión

#!/bin/bash   
#One Piece Manga reminder    
#I created a file named .newop that contains the latest chapter.    
let new=$(cat ~/.newop)    
wget --read-timeout=30 -t20 -O .opreminder.txt http://www.mangareader.net/103/one-piece.html

if (( $(cat .opreminder.txt | grep "One Piece $new" | wc -l) >=1 ))    
then    
    (( new+=1 ))    
    echo $new    
    echo $new > ~/.newop    
    notify-send "A new chapter of One Piece was released."    
else    
    notify-send "No new chapter for One Piece."    
    notify-send "The latest chapter is still $new."    
fi        
exit

Y esto es lo que escribí en mi crontab

0,15,30,45 12-23 * * 3   /home/jchester/bin/opreminder.sh
usuario158335
fuente
Solo un recordatorio, todos los comandos en crontab deben tener su ruta delante de ellos mientras se ejecutan como root. Adjuntar script y línea en crontab ayudaría, de lo contrario, solo estamos adivinando su problema
Meer Borg
Si lo siento Lo acabo de hacer.
user158335
Esta es una mala idea. Las notificaciones son una cosa de "GUI", cron es una cosa de "consola". No hay ninguna garantía de que lib-notify pueda encontrar una manera de mostrar el mensaje. En su lugar, debería considerar enviar datos a stdout y dejar que los mensajes de cron se encarguen de enviar la información. Normalmente se envía un correo electrónico.
coteyr
2
En algunos casos, la variable de ajuste de la pantalla hacia arriba puede ayudar, así, por ejemplo: export DISPLAY=:0.
Glutanimate
1
Para 16.04, este funcionó para mí */1 * * * * eval "export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ)";/usr/bin/notify-send -i appointment -c "im" "Keep Working"
KrIsHnA

Respuestas:

18

Los comandos deben hacer referencia a su ubicación. Entonces notify-sendnecesita ser/usr/bin/notify-send

Todos los comandos deben tener su ruta completa.

Use el whereis notify-sendcomando para ver dónde "viven" sus comandos

Meer Borg
fuente
2
¿Eso incluye cat, wget, if, let, grep, echo, etc.?
user158335
77
Al menos en mi sistema, notify-sendestá a la PATHaltura de un trabajo cron. Vea mi respuesta a continuación.
krlmlr
2
No es la solución para Ubuntu 17.04. Ver askubuntu.com/a/472769/413683 y askubuntu.com/a/834479/413683 en su lugar.
Mateusz Piotrowski,
2
Este no es el problema. El problema es que los scripts cron no se ejecutan en la sesión del usuario y no tienen un concepto del entorno de la sesión de inicio de sesión del usuario. Como la notificación de envío requiere conectarse a un bus de sesión dbus para enviar la notificación, no importa desde qué ruta se llame el binario, cuando no se conecta al bus de sesión correcto.
dobey
2
Esta NO es la respuesta. Claro, si el ejecutable no se puede ubicar, no se ejecutará, PERO: 1. notify-send está en la RUTA, por lo que se ubicará 2. incluso si no estaba en la RUTA, y usted especifica la ruta completa, todavía lo hará no funciona, porque en realidad DBUS_SESSION_BUS_ADDRESS tiene que configurarse para notificar-enviar. Y la respuesta correcta es de kmir.
Kris Jace
31

Las cosas parecen ser diferentes en 13.04, al menos en Gnome Shell.

Primero, esto es lo que se envimprime cuando se ejecuta desde el zzyxytrabajo cron del usuario (no del root):

HOME=/home/zzyxy
LOGNAME=zzyxy
PATH=/usr/bin:/bin
XDG_RUNTIME_DIR=/run/user/zzyxy
LANG=en_US.UTF-8
SHELL=/bin/sh
PWD=/home/zzyxy

Para ponerse notify-senda trabajar, parece ser necesario establecer la DBUS_SESSION_BUS_ADDRESSvariable de entorno, según el comentario de DahitiF en ubuntuforums.org. Simplemente anteponga lo siguiente a su descripción de trabajo real:

eval "export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ)";

No parece ser necesario configurarlo DISPLAY.

krlmlr
fuente
44
Gracias, esto es lo que finalmente funcionó para mí. En Xubuntu, tienes que cambiar gnome-sessiona xfce4-session.
shrx
Esta es la única respuesta para trabajar para 14.04, junto con la pista obvia de la aceptada.
Wtower
1
No tenía gnome-sessiony usé en su gnome-shelllugar (tenga cuidado, también hay un gnome-shell-calendar-serverasí pgrepque obtendrá 2 pids). También lo necesitaba DISPLAY=:0porque estoy usando 2 pantallas físicas y no estaba definido. ¡Gracias!
soyuka
Si está utilizando Openbox (como en CB ++), cambie openboxpor gnome-session.
ACK_stoverflow
ESTA es la respuesta correcta, y la respuesta aceptada ni siquiera es correcta, habla de la variable DISPLAY que ni siquiera es necesaria, ni resuelve el problema.
Kris Jace
24

El comando notify-sendno muestra el mensaje en la pantalla cuando lo inicia cron. Simplemente agregue la pantalla de destino en la parte superior de su script, por ejemplo:

export DISPLAY=:0
Martin Höger
fuente
Esto es lo que tuve que hacer en 14.10 también. De lo contrario, obtendría este errorgdk_mir_display_open Failed to connect to Mir: Failed to connect to server socket: No such file or directory Option parsing failed: Cannot open display:
Joelmob
1
Esta. Y utilícelo echo $DISPLAYen un terminal para asegurarse de que su pantalla realmente lo sea :0(generalmente lo es, pero no siempre)
Mark
Solo esto funcionó para mí, estoy usando Linux Mint
Harendra Singh
5

Al menos para Ubuntu 14.04, la respuesta anterior de klrmr es la respuesta correcta. No parece ser necesario configurar DISPLAY o articular rutas completas para notificar-enviar o cualquier otra cosa normalmente en $ PATH.

A continuación se muestra un script cron que estoy usando para apagar una máquina virtual cuando el estado de la batería de una computadora portátil es demasiado bajo. La configuración de línea DBUS_SESSION_BUS_ADDRESS en la respuesta de klrmr anterior es la modificación que finalmente hizo que las advertencias funcionaran correctamente.

#!/bin/bash

# if virtual machine is running, monitor power consumption
if pgrep -x vmware-vmx; then
  bat_path="/sys/class/power_supply/BAT0/"
  if [ -e "$bat_path" ]; then
    bat_status=$(cat $bat_path/status)
    if [ "$bat_status" == "Discharging" ]; then
      bat_current=$(cat $bat_path/capacity)
      # halt vm if critical; notify if low
      if [ "$bat_current" -lt 10 ]; then
        /path/to/vm/shutdown/script
        echo "$( date +%Y.%m.%d_%T )" >> "/home/user/Desktop/VM Halt Low Battery"
        elif [ "$bat_current" -lt 15 ]; then
            eval "export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ)";
            notify-send -i "/usr/share/icons/ubuntu-mono-light/status/24/battery-caution.svg"  "Virtual machine will halt when battery falls below 10% charge."
      fi
    fi
  fi
fi

exit 0
nmax
fuente
Esta fue la solución que también funcionó perfectamente para mí, solo agregué la línea "eval ..." a mi script que ejecuté desde crontab - ahora funciona perfectamente
Mtl Dev
2

En mi caso con ubuntu 16.04 se requería una ruta explícita, resuelvo el problema simplemente agregando

PANTALLA =: 0

en las primeras líneas del crontab, antes de la llamada notificar-enviar.

Raul R.
fuente
Esto es lo único necesario para que funcione en 16.04.
Jonathan Landrum
1

El primer culpable es su archivo crontab, también debe mencionar el nombre de usuario con el que se debe ejecutar el script, mejor mantenerlo como root

0,15,30,45 12-23 * * 3 root   /home/jchester/bin/opreminder.sh

y luego debe usar el nombre de usuario del usuario de la GUI dentro del script y anteponerlo para notificar-enviar con "sudo o su" para ejecutar el comando como un usuario que posee la GUI

ejemplo:

su gnome_user_name -c 'notify-send "summary" "body"'

o

sudo -u gnome_user_name notify-send "summary" "body"

¿Dónde gnome_user_nameestá el nombre de usuario del usuario que inició la sesión GUI? Es usted quien inició sesión, y si desea que sea una elección dinámica, puede obtenerlo de

GNOME_USER=`ps -eo uname,cmd | grep gnome-session| head -1 | cut -d' ' -f1 `

ejemplo:

su $GNOME_USER -c 'notify-send "summary" "body"'

o

sudo -u $GNOME_USER notify-send "summary" "body"
S471
fuente
1
Creo que cuando su nombre de usuario tiene más de X caracteres, su usernma se trunca: por ejemplo, mi nombre de usuario es oniltonmaciel, pero $GNOME_USERse mostraría onilton+(no funciona)
Onilton Maciel
lo arregló con un mejor comando
S471
1

La forma en que el binario recupera la dirección dbus parece haber cambiado últimamente. En Ubuntu 15.04 (Vivid Vervet) con "notificar-enviar 0.7.6", se necesitan las siguientes dos variables:

export HOME=/home/$notify_user
export DISPLAY=:0.0

La declaración de 'krlmlr' se evalúa bien y establece la dirección correcta, pero el diálogo no aparecerá desde un trabajo cron.

tanza
fuente
0

Si su script en crontab se ejecuta como root, las respuestas anteriores probablemente no funcionarán. Pruebe esta función, que funciona bien para mí en 16.04:

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 
}

(Fuente: https://unix.stackexchange.com/a/344377/7286 )

mivk
fuente
0

Es mejor confiar en el dbus-sessionproceso, debería ejecutarse para todos los sistemas donde DBUS_SESSION_BUS_ADDRESSestá presente.

Crea un script:

#!/bin/bash
# notify.sh

environs=`pidof dbus-daemon | tr ' ' '\n' | awk '{printf "/proc/%s/environ ", $1}'`
export DBUS_SESSION_BUS_ADDRESS=`cat $environs 2>/dev/null | tr '\0' '\n' | grep DBUS_SESSION_BUS_ADDRESS | cut -d '=' -f2-`
export DISPLAY=:0

notify-send "It works!"

Hazlo ejecutable:

$ chmod +x ~/notify.sh

Agréguelo a crontab:

* * * * * $HOME/notify.sh
denis.peplin
fuente
0

Esto tardó una eternidad en hacer que el trabajo en ubuntu 15.10, Tuviese que agregar una fuente para que los usuarios tengan un entorno normal. mi pantalla fue: 1 por alguna razón también. Utilizando los primeros resultados de gnome-session pid para la búsqueda DBUS_SESSION_BUS_ADDRESS.

# Crontab is
* 21 * * * /bin/sh /home/tristik/cron.sh
#!/bin/sh 
# cron.sh
# Notifies the user of date and time
source /home/tristik/.bashrc
pid=$(pgrep -u tristik gnome-session | head -n 1)
dbus=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$pid/environ | sed 's/DBUS_SESSION_BUS_ADDRESS=//' )
export DBUS_SESSION_BUS_ADDRESS=$dbus
export HOME=/home/tristik
export DISPLAY=:1
/usr/bin/notify-send 'title' "$(/bin/date)"
Tristik
fuente
0

Acabo de hacer que esto funcione con el escritorio de canela en Ubuntu 15.10, usando la siguiente receta:

if [ ! -v DBUS_SESSION_BUS_ADDRESS ]; then
  pid=$(pgrep -u $LOGNAME cinnamon-sessio)
  eval "export $(\grep -z DBUS_SESSION_BUS_ADDRESS /proc/$pid/environ)"
fi
notify-send "$RESUME" "$INFO"

El truco fue darse cuenta de que 'canela-sesión' es demasiado larga para que pgrep encuentre:

$ pgrep -u $LOGNAME cinnamon-session
$ pgrep -u $LOGNAME cinnamon
30789
30917
30965
30981
31039
31335
$ ps -a | \grep cinnamon
30789 tty2     00:00:00 cinnamon-sessio
30917 tty2     00:00:02 cinnamon-settin
30965 tty2     00:00:00 cinnamon-launch
30981 tty2     00:04:15 cinnamon
31039 tty2     00:00:00 cinnamon-killer
31335 tty2     00:00:00 cinnamon-screen
$ ps a | \grep cinnamon
 4263 pts/1    S+     0:00 grep cinnamon
30779 tty2     Ssl+   0:00 /usr/lib/gdm/gdm-x-session --run-script cinnamon-session-cinnamon
30789 tty2     Sl+    0:00 cinnamon-session --session cinnamon
30917 tty2     Sl+    0:02 /usr/lib/x86_64-linux-gnu/cinnamon-settings-daemon/cinnamon-settings-daemon
30965 tty2     Sl+    0:00 /usr/bin/python2 /usr/bin/cinnamon-launcher
30970 tty2     Sl+    0:00 /usr/lib/x86_64-linux-gnu/cinnamon-settings-daemon/csd-printer
30981 tty2     Sl+    4:16 cinnamon --replace
31039 tty2     Sl+    0:00 /usr/bin/python2 /usr/bin/cinnamon-killer-daemon
31335 tty2     Sl+    0:00 cinnamon-screensaver
$ pgrep -u $LOGNAME cinnamon-sessio
30789

También tuve que usar \ grep porque mi grep tiene un alias para

$ alias grep
alias grep='grep -n --color=always'
John Frankland
fuente
0

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
0

Problema causado al llamar python3a crontab con UTF-8locale.

TL; DR: llamada de prefijo en crontab w / locale como en:

*/5 * * * * LC_ALL=en_US.utf-8 LANG=en_US.utf-8 ~/.local/bin/watson-notify

Ver también click y python3 :

Traceback (most recent call last):
  File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/usr/lib/python3/dist-packages/watson/__main__.py", line 6, in <module>
    cli.cli()
  File "/usr/lib/python3/dist-packages/click/core.py", line 759, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 693, in main
    _verify_python3_env()
  File "/usr/lib/python3/dist-packages/click/_unicodefun.py", line 123, in _verify_python3_env
    'for mitigation steps.' + extra)
RuntimeError: Click will abort further execution because Python 3 was configured to use ASCII as encoding for the environment.  Consult http://click.pocoo.org/python3/ for mitigation steps.

This system supports the C.UTF-8 locale which is recommended.
You might be able to resolve your issue by exporting the
following environment variables:

    export LC_ALL=C.UTF-8
    export LANG=C.UTF-8
Gen.Stack
fuente
0

Para todos los guiones crontab que usan libnotify, uso esto:

notify_user() {
    local user=$(whoami)
    notify-send -u normal -t 4000 "System Backup" "Starting backup"
}

notify_user # and do other stuff

Funciona incluso si uso cron en modo raíz.

azzamsa
fuente
0

Todo lo que necesitas es X_user y X_userid. Reemplace ambos en el siguiente comando.

Solución con systemd

/etc/systemd/system/opreminder.service #Service file

[Unit]
Descrption=some service to run

[Service]
User=[X_user]
ExecStart=/home/jchester/bin/opreminder.sh


/etc/systemd/system/opreminder.timer #timer file

[Unit]
Description=Some desc


[Timer]
OnCalendar=0,15,30,45 12-23 * * 3 

[Install]
WantedBy=list.timer.target

/home/jchester/bin/opreminder.sh #El script

#!/usr/bin/env bash

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.'

No es necesario usar sudo -u si el archivo de servicio ya está configurado con el usuario deseado

Fuente: https://wiki.archlinux.org/index.php/Desktop_notifications#Usage_in_programming

Bruno
fuente