Notify-send ne fonctionne pas depuis crontab

44

J'ai créé un script qui devrait m'avertir quand je lis un nouveau chapitre du manga. J'ai utilisé la commande notify-send pour le faire. Le programme fonctionne lorsque j'essaie de l'exécuter dans un terminal. La notification est affichée. Cependant, lorsque j'ai placé ceci dans ma crontab, la notification ne s'affiche pas. Je suis à peu près sûr que le programme est en cours d'exécution depuis que je l'ai créé pour créer un fichier pour moi. Le fichier a été créé, mais la notification ne s’est pas affichée.

Voici mon script

#!/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

Et voici ce que j'ai écrit dans ma crontab

0,15,30,45 12-23 * * 3   /home/jchester/bin/opreminder.sh
utilisateur158335
la source
Juste un rappel, toutes les commandes de crontab doivent avoir leur chemin devant elles car elles s'exécutent en tant que root. L'attachement du script et de la ligne dans crontab nous aiderait sinon nous devinons simplement votre problème
Plus d'infos Bain
Ouais désolé. Je viens de faire.
user158335
C'est une mauvaise idée. Les notifications sont une "interface graphique", cron est une "console". Lib-notify ne sera pas en mesure de trouver un moyen d’afficher le message. Au lieu de cela, vous devriez envisager d’envoyer des données à stdout et laisser la messagerie de cron se charger de l’envoi des informations. Normalement, un email est envoyé.
coteyr
2
Dans certains cas , fixer la variable DISPLAY , on l' aidera ainsi, par exemple: export DISPLAY=:0.
Glutanimate
1
Pour 16.04, celui - ci a fonctionné pour moi */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

Réponses:

18

Les commandes doivent référencer leur emplacement. Donc notify-senddoit être/usr/bin/notify-send

Toutes les commandes doivent avoir leur chemin complet.

Utilisez la whereis notify-sendcommande pour voir où "vivent" vos commandes

Meer Borg
la source
2
Est-ce que cela inclut cat, wget, if, let, grep, echo, etc.?
user158335
7
Au moins sur mon système, notify-sendest sur le PATHmême pour un travail cron. Voir ma réponse ci-dessous.
krlmlr
2
Ce n'est pas la solution pour Ubuntu 17.04. Voir askubuntu.com/a/472769/413683 et askubuntu.com/a/834479/413683 à la place.
Mateusz Piotrowski
2
Ce n'est pas le problème. Le problème est que les scripts cron ne s'exécutent pas sous la session utilisateur et n'ont aucun concept de l'environnement de la session de connexion de l'utilisateur. Comme notify-send nécessite la connexion à un bus de session dbus pour envoyer la notification, le chemin depuis lequel le binaire est appelé n’aura pas d'importance, s'il ne se connecte pas au bon bus de session.
dobey
2
Ce n'est pas la réponse. Bien sûr, si l'exécutable ne peut pas être localisé, il ne fonctionnera pas, MAIS: 1. notify-send est sur le PATH, donc il sera localisé 2. même s'il ne l'était pas, et que vous spécifiez le chemin complet, ne fonctionne pas, car DBUS_SESSION_BUS_ADDRESS doit en réalité être défini pour notify-send. Et la bonne réponse est de kmir.
Kris Jace le
31

Les choses semblent être différentes le 13.04, du moins dans Gnome Shell.

Tout d’abord, voici ce qui est envimprimé lorsqu’il est exécuté à partir zzyxydu travail cron de l’utilisateur (et non de celui de la racine):

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

Pour se rendre notify-sendau travail, il semble nécessaire de définir la DBUS_SESSION_BUS_ADDRESSvariable d'environnement, comme le commentait DahitiF sur ubuntuforums.org. Ajoutez simplement ce qui suit à la description de votre travail actuel:

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

Il ne semble pas nécessaire de définir DISPLAY.

krlmlr
la source
4
Merci, c'est ce qui a finalement fonctionné pour moi. Sur Xubuntu, vous devez passer gnome-sessionà xfce4-session.
Shin
C’est la seule réponse possible pour 14.04, avec l’allusion évidente de celle acceptée.
Wtower
1
Je n'avais pas gnome-sessionet utilisé à la gnome-shellplace (attention il y a aussi une gnome-shell-calendar-serversorte pgrepsera obtenir 2 PIDS). J'avais aussi besoin DISPLAY=:0parce que j'utilise 2 écrans physiques et que cela n'a pas été défini. Merci!
soyuka
Si vous utilisez Openbox (comme sur CB ++), échangez openboxpour gnome-session.
ACK_stoverflow
CECI est la bonne réponse, et la réponse acceptée n’est même pas correcte, il est question de la variable DISPLAY qui n’est même pas nécessaire et qui ne résout pas le problème.
Kris Jace
24

La commande notify-sendn’affichera pas le message sur votre écran si elle est lancée par cron. Ajoutez simplement l'affichage cible en haut de votre script, par exemple:

export DISPLAY=:0
Martin Höger
la source
C'est ce que je devais faire en 14h10 aussi. Sinon, j'aurais cette erreurgdk_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
Cette. Et utilisez-le echo $DISPLAYdans un terminal pour vous assurer que votre écran le soit vraiment :0(comme d'habitude, mais pas toujours).
Mark
Seulement ceci a fonctionné pour moi, j'utilise Linux Mint
Harendra Singh
5

Pour Ubuntu 14.04 au moins, la réponse de klrmr ci - dessus est la bonne réponse. Il ne semble pas nécessaire de définir DISPLAY ou d’articuler des chemins complets pour notify-send ou quoi que ce soit normalement dans $ PATH.

Vous trouverez ci-dessous un script cron que j'utilise pour arrêter une machine virtuelle lorsque l'état de la batterie d'un ordinateur portable devient trop faible. Le paramètre de ligne DBUS_SESSION_BUS_ADDRESS dans la réponse de klrmr ci-dessus est la modification qui a finalement permis aux avertissements de fonctionner correctement.

#!/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
la source
C’est la solution qui a parfaitement fonctionné pour moi également. Je viens d’ajouter à mon script la ligne "eval ..." que je lance depuis crontab - maintenant, il fonctionne parfaitement
Mtl Dev
2

Dans mon cas avec Ubuntu 16.04, tout chemin explicite était requis, je résous le problème en ajoutant simplement

AFFICHAGE =: 0

aux premières lignes de la crontab, avant l'appel notify-send.

Raul R.
la source
C'est la seule chose nécessaire pour le faire fonctionner le 16.04.
Jonathan Landrum
1

Le premier responsable est votre fichier crontab, vous devez également mentionner le nom d'utilisateur avec lequel le script doit être exécuté. Il est préférable de le conserver en tant que root.

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

et ensuite vous devez utiliser le nom d'utilisateur de l'utilisateur d'interface graphique dans le script et le préfixer de façon à notifier-envoyer avec "sudo ou su" pour exécuter la commande en tant qu'utilisateur propriétaire de l'interface graphique.

Exemple :

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

ou

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

gnome_user_nameest le nom d'utilisateur de l'utilisateur qui a démarré la session graphique, c'est vous qui vous êtes connecté, et si vous voulez en faire une sélection dynamique, vous pouvez l'obtenir à partir de

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

Exemple :

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

ou

sudo -u $GNOME_USER notify-send "summary" "body"
S471
la source
1
Je pense que lorsque votre nom d'utilisateur est plus long que X caractères, votre nom d'utilisateur est tronqué: Par exemple, mon nom d'utilisateur est oniltonmaciel, mais $GNOME_USERindiquerait onilton+(ne fonctionne pas)
Onilton Maciel
corrigé avec une meilleure commande
S471
1

La façon dont le binaire récupère l'adresse dbus semble avoir changé récemment. Sur Ubuntu 15.04 (Vivid Vervet) avec "notify-send 0.7.6", les deux variables suivantes sont nécessaires:

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

L'instruction de 'krlmlr' évalue correctement et définit l'adresse correcte, mais la boîte de dialogue ne s'ouvre pas à partir d'un travail cron.

Tanza
la source
0

Si votre script dans crontab est exécuté en tant que root, les réponses ci-dessus ne fonctionneront probablement pas. Essayez cette fonction, qui me convient très bien 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 
}

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

mivk
la source
0

Mieux vaut compter sur le dbus-sessionprocessus, il devrait être en cours d’exécution pour tous les systèmes où il DBUS_SESSION_BUS_ADDRESSest présent.

Créez 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!"

Rendez-le exécutable:

$ chmod +x ~/notify.sh

Ajoutez-le à crontab:

* * * * * $HOME/notify.sh
denis.peplin
la source
0

Cela a pris une éternité pour faire fonctionner ubuntu 15.10, il a fallu ajouter une source pour que les utilisateurs env env normaux. mon affichage était: 1 pour une raison également. Utilisation du pid des premiers résultats de gnome-session pour la recherche 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
la source
0

Je viens de recevoir ceci pour fonctionner avec le bureau cannelle sur Ubuntu 15.10, en utilisant la recette suivante:

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"

L'astuce consistait à réaliser que la «session de cannelle» est trop longue pour que pgrep puisse trouver:

$ 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

J'ai aussi dû utiliser \ grep car mon grep est alias

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

J'utilise i3 sur Ubuntu 18.04. Ma façon de résoudre ceci est:

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

M. Goferito
la source
0

Problème provoqué par l'appel python3de crontab avec UTF-8locale.

TL; DR: appel préfixe dans crontab w / locale comme dans:

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

Voir aussi click et 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
Gén.Stack
la source
0

Pour tous les scripts crontab utilisant libnotify, j'utilise ceci:

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

notify_user # and do other stuff

Cela fonctionne même si j'utilise cron en mode racine.

azzamsa
la source
0

Tout ce dont vous avez besoin est X_user et X_userid. Remplacez les deux dans la commande ci-dessous.

Solution avec systemd

/etc/systemd/system/opreminder.service # fichier de service

[Unit]
Descrption=some service to run

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


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

[Unit]
Description=Some desc


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

[Install]
WantedBy=list.timer.target

/home/jchester/bin/opreminder.sh #Le 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.'

Pas besoin d'utiliser sudo -u si le fichier de service est déjà défini avec l'utilisateur prévu

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

Bruno
la source