Notifica-invio non funziona da crontab


44

Ho realizzato una sceneggiatura che dovrebbe avvisarmi quando sto leggendo un nuovo capitolo del manga. Ho usato il comando notification-send per fare questo. Il programma funziona quando sto cercando di eseguirlo nel terminale. La notifica sta mostrando. Tuttavia, quando l'ho inserito nel mio crontab, la notifica non viene visualizzata. Sono abbastanza sicuro che il programma sia in esecuzione da quando l'ho creato per creare un file per me. Il file è stato creato, ma la notifica non è stata visualizzata.

Ecco la mia sceneggiatura

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

Ed ecco cosa ho scritto nel mio crontab

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

Solo un promemoria, tutti i comandi in crontab devono avere il loro percorso davanti a loro mentre corrono come root. Allegare script e line in crontab sarebbe di aiuto, altrimenti indoviniamo solo il tuo problema
Meer Borg

Si scusa. L'ho appena fatto.
user158335

Questa è una cattiva idea. Le notifiche sono una cosa "GUI", cron è una cosa "console". Non esiste alcun garante che lib-notification sarà in grado di trovare un modo per visualizzare il messaggio. Invece dovresti considerare di inviare dati a stdout e lasciare che la messaggistica di cron si occupi di inviare le informazioni. Normalmente viene inviata un'e-mail.
Coteyr,

2
In alcuni casi, impostando la variabile DISPLAY up può aiutare pure, ad esempio: export DISPLAY=:0.
Glutanimate,

1
Perché 16.04, questo ha funzionato per me */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 l'

Risposte:


18

I comandi devono fare riferimento alla loro posizione. Quindi notify-senddeve essere/usr/bin/notify-send

Tutti i comandi devono avere il loro percorso completo.

Usa il whereis notify-sendcomando per vedere dove "vivono" i tuoi comandi


2
Questo include cat, wget, if, let, grep, echo, ecc?
user158335

7
Almeno sul mio sistema, notify-sendè in PATHpareggio per un lavoro cron. Vedi la mia risposta qui sotto.
krlmlr,

2
Non è la soluzione per Ubuntu 17.04. Vedi askubuntu.com/a/472769/413683 e askubuntu.com/a/834479/413683 invece.
Mateusz Piotrowski

2
Questo non è il problema. Il problema è che gli script cron non vengono eseguiti nella sessione utente e non hanno alcun concetto dell'ambiente della sessione di accesso dell'utente. Poiché la notifica-invio richiede la connessione a un bus di sessione dbus per inviare la notifica, non importa quale percorso viene chiamato il binario, quando non si connette al bus di sessione corretto.
dobey,

2
Questa NON è la risposta. Certo, se l'eseguibile non può essere localizzato, non funzionerà, MA: 1. notification-send è sul PERCORSO, quindi sarà localizzato 2. anche se non fosse sul PERCORSO, e specifichi il percorso completo che continuerà comunque non funziona, perché in realtà DBUS_SESSION_BUS_ADDRESS deve essere impostato per notifica-invio. E la risposta corretta è di kmir.
Kris Jace il

31

Le cose sembrano essere diverse il 13.04, almeno in Gnome Shell.

Innanzitutto, questo è ciò che viene envstampato quando eseguito dal zzyxycron job dell'utente (non di 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

Per mettersi notify-sendal lavoro, sembra necessario impostare la DBUS_SESSION_BUS_ADDRESSvariabile d'ambiente, come da commento di DahitiF su ubuntuforums.org. Basta anteporre quanto segue alla descrizione del lavoro effettivo:

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

Non sembra essere necessario impostare DISPLAY.


4
Grazie, questo è quello che alla fine ha funzionato per me. Su Xubuntu, devi passare gnome-sessiona xfce4-session.
Shrx

Questa è l'unica risposta al lavoro per il 14.04, insieme all'ovvio accenno di quello accettato.
Wtower,

1
Invece non l'ho gnome-sessionusato e usato gnome-shell(attenzione, c'è anche un gnome-shell-calendar-serverquindi pgrepotterremo 2 pids). Ho anche bisogno DISPLAY=:0perché sto usando 2 schermi fisici e non è stato definito. Grazie!
soyuka,

Se stai usando Openbox (come su CB ++), scambia openboxper gnome-session.
ACK_stoverflow,

QUESTA è la risposta corretta e la risposta accettata non è nemmeno corretta, parla della variabile DISPLAY che non è nemmeno necessaria, né risolve effettivamente il problema.
Kris Jace,

24

Il comando notify-sendnon mostra il messaggio sullo schermo quando viene avviato da cron. Aggiungi semplicemente la visualizzazione target nella parte superiore dello script, ad esempio:

export DISPLAY=:0

Questo è quello che dovevo fare anche nel 14.10. Altrimenti gdk_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:
otterrei

1
Questo. E usalo echo $DISPLAYin un terminale per assicurarti che lo schermo sia realmente :0(di solito lo è, ma non sempre).
Segna il

Solo questo ha funzionato per me, sto usando Linux Mint
Harendra Singh il

5

Almeno per Ubuntu 14.04, la risposta di klrmr sopra è la risposta corretta. Non sembra necessario impostare DISPLAY o articolare percorsi completi per notifica-invio o qualsiasi altra cosa normalmente in $ PATH.

Di seguito è riportato uno script cron che sto usando per arrestare una macchina virtuale quando lo stato della batteria di un laptop diventa troppo basso. L'impostazione della riga DBUS_SESSION_BUS_ADDRESS nella risposta di klrmr sopra è la modifica che alla fine ha fatto funzionare correttamente gli avvisi.

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

Questa è stata la soluzione che ha funzionato perfettamente anche per me, ho appena aggiunto la riga "eval ..." alla mia sceneggiatura che eseguo da crontab - ora funziona perfettamente
Mtl Dev

2

Nel mio caso con Ubuntu 16.04 era necessario un percorso esplicito, risolvo il problema semplicemente aggiungendo

DISPLAY =: 0

alle prime linee del crontab, prima di chiamare notification-send.


Questa è l'unica cosa necessaria per farlo funzionare su 16.04.
Jonathan Landrum,

1

Il primo colpevole è il tuo file crontab, devi anche menzionare il nome utente con cui lo script deve essere eseguito, meglio tenerlo come root

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

e quindi dovresti usare il nome utente dell'utente GUI all'interno dello script e anteporre a notifica-invio con "sudo o su" per eseguire il comando come utente proprietario della GUI

esempio :

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

o

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

dov'è gnome_user_nameil nome utente dell'utente che ha avviato la sessione della GUI sei tu che hai effettuato l'accesso e se vuoi renderlo una scelta dinamica, puoi ottenerlo da

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

esempio :

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

o

sudo -u $GNOME_USER notify-send "summary" "body"

1
Penso che quando il tuo nome utente è più lungo di X caratteri, il tuo usernma viene troncato: ad esempio, il mio nome utente è oniltonmaciel, ma $GNOME_USERmostrerebbe onilton+(non funziona)
Onilton Maciel

risolto con un comando migliore
S471,

1

Il modo in cui il binario recupera l'indirizzo dbus sembra essere cambiato di recente. Su Ubuntu 15.04 (Vivid Vervet) con "notify-send 0.7.6", sono necessarie le seguenti due variabili:

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

L'istruzione di 'krlmlr' valuta bene e imposta l'indirizzo corretto, ma la finestra di dialogo non verrà visualizzata da un processo cron.


0

Se il tuo script in crontab è in esecuzione come root, probabilmente le risposte sopra non funzioneranno. Prova questa funzione, che funziona bene per me in 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 
}

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


0

Meglio fare affidamento sul dbus-sessionprocesso, dovrebbe essere in esecuzione per tutti i sistemi in cui DBUS_SESSION_BUS_ADDRESSè presente.

Crea uno 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!"

Renderlo eseguibile:

$ chmod +x ~/notify.sh

Aggiungilo a crontab:

* * * * * $HOME/notify.sh

0

Questo ha impiegato un'eternità a funzionare su Ubuntu 15.10, ho dovuto aggiungere una fonte per ottenere gli utenti normali. il mio display era: 1 anche per qualche motivo. L'uso del pid dei primi risultati della sessione di gnome per la ricerca 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)"

0

Ho appena ottenuto questo per funzionare con il desktop cannella su Ubuntu 15.10, usando la seguente ricetta:

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"

Il trucco era rendersi conto che la "sessione di cannella" è troppo lunga per essere trovata da pgrep:

$ 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

Ho anche dovuto usare \ grep perché il mio grep è aliasato

$ alias grep
alias grep='grep -n --color=always'

0

Uso i3 su Ubuntu 18.04. Il mio modo di risolvere questo è:

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


0

Problema causato dalla chiamata python3in crontab con impostazioni UTF-8internazionali.

TL; DR: chiamata prefisso in crontab con impostazioni locali come in:

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

Vedi anche click e 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

0

Per tutti gli script crontab che usano libnotify, io uso questo:

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

notify_user # and do other stuff

Funziona anche se uso cron in modalità root.


0

Tutto ciò che serve è X_user e X_userid. Sostituire entrambi nel seguente comando.

Soluzione 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 #Lo 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.'

Non è necessario utilizzare sudo -u se il file di servizio è già impostato con l'utente previsto

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.