Beritahu-kirim tidak berfungsi dari crontab

44

Saya membuat naskah yang harus memberi tahu saya ketika ada bab manga baru yang saya baca. Saya menggunakan perintah notify-send untuk melakukan ini. Program ini berfungsi ketika saya mencoba menjalankannya di terminal. Pemberitahuan ditampilkan. Namun, ketika saya meletakkan ini di crontab saya, notifikasi tidak muncul. Saya cukup yakin bahwa program ini berjalan sejak saya membuatnya untuk membuat file untuk saya. File itu dibuat, tetapi notifikasi tidak muncul.

Ini skrip saya

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

Dan inilah yang saya tulis di crontab saya

0,15,30,45 12-23 * * 3   /home/jchester/bin/opreminder.sh
pengguna158335
sumber
Sebagai pengingat, semua perintah di crontab harus memiliki path di depannya saat dijalankan sebagai root. Melampirkan skrip dan baris di crontab akan membantu jika tidak, kami hanya menebak masalah Anda
Meer Borg
Ya maaf Saya baru saja melakukannya.
user158335
Ini ide yang buruk. Notifikasi adalah hal "GUI", cron adalah hal "konsol". Tidak ada jaminan bahwa lib-notify akan dapat menemukan cara untuk menampilkan pesan. Alih-alih, Anda harus mempertimbangkan mengirim data ke stdout dan membiarkan pesan cron menangani pengiriman info. Biasanya email dikirim.
coteyr
2
Dalam beberapa kasus pengaturan DISPLAY variabel up dapat membantu juga, misalnya: export DISPLAY=:0.
Glutanimate
1
Karena 16.04, yang ini bekerja untuk saya */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

Jawaban:

18

Perintah perlu merujuk lokasi mereka. Jadi notify-sendperlu begitu/usr/bin/notify-send

Semua perintah harus memiliki path lengkapnya.

Gunakan whereis notify-sendperintah untuk melihat di mana perintah Anda "hidup"

Meer Borg
sumber
2
Apakah itu termasuk cat, wget, if, let, grep, echo, dll?
user158335
7
Setidaknya di sistem saya, notify-sendada di PATHbahkan untuk pekerjaan cron. Lihat jawaban saya di bawah ini.
krlmlr
2
Ini bukan solusi untuk Ubuntu 17.04. Lihat askubuntu.com/a/472769/413683 dan minta askubuntu.com/a/834479/413683 sebagai gantinya.
Mateusz Piotrowski
2
Ini bukan masalahnya. Masalahnya adalah skrip cron tidak berjalan di bawah sesi pengguna, dan tidak memiliki konsep lingkungan dari sesi login pengguna. Karena notify-send memerlukan koneksi ke bus sesi dbus untuk mengirim notifikasi, tidak peduli dari mana jalur biner berasal, ketika itu tidak terhubung ke bus sesi yang benar.
dobey
2
Ini BUKAN jawabannya. Tentu, jika executable tidak dapat ditemukan, itu tidak akan berjalan, TETAPI: 1. beri tahu-kirim ada di PATH sehingga akan ditemukan 2. bahkan jika itu tidak ada di PATH, dan Anda tentukan path lengkapnya masih akan tidak berfungsi, karena sebenarnya DBUS_SESSION_BUS_ADDRESS harus disetel untuk notifikasi-kirim. Dan jawaban yang benar adalah dari kmir.
Kris Jace
31

Sepertinya ada yang berbeda pada 13,04, setidaknya di Gnome Shell.

Pertama, inilah yang envdicetak saat dijalankan dari zzyxytugas cron pengguna (bukan 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

Untuk mulai notify-sendbekerja, tampaknya perlu untuk mengatur DBUS_SESSION_BUS_ADDRESSvariabel lingkungan, sesuai komentar DahitiF di ubuntuforums.org. Hanya tambahkan yang berikut ini ke deskripsi pekerjaan Anda yang sebenarnya:

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

Tampaknya tidak perlu diatur DISPLAY.

krlmlr
sumber
4
Terima kasih, inilah yang akhirnya berhasil untuk saya. Di Xubuntu, Anda harus mengubah gnome-sessionke xfce4-session.
shrx
Ini adalah satu-satunya jawaban untuk bekerja untuk 14,04, bersama dengan petunjuk yang jelas dari jawaban yang diterima.
Wtower
1
Saya tidak punya gnome-sessiondan menggunakan gnome-shellsebagai gantinya (hati-hati juga ada gnome-shell-calendar-serversehingga pgrepakan mendapat 2 pids). Saya juga diperlukan DISPLAY=:0karena saya menggunakan 2 layar fisik dan tidak ditentukan. Terima kasih!
soyuka
Jika Anda menggunakan Openbox (seperti pada CB ++) tukar openboxuntuk gnome-session.
ACK_stoverflow
INI adalah jawaban yang benar, dan jawaban yang diterima bahkan tidak benar, ini berbicara tentang variabel DISPLAY yang bahkan tidak diperlukan, juga tidak benar-benar menyelesaikan masalah.
Kris Jace
24

Perintah notify-sendtidak akan menampilkan pesan di layar Anda ketika dimulai dengan cron. Cukup tambahkan tampilan target di bagian atas skrip Anda, misalnya:

export DISPLAY=:0
Martin Höger
sumber
Ini juga yang harus saya lakukan pada jam 14.10. Kalau tidak, saya akan mendapatkan kesalahan inigdk_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
Ini. Dan gunakan echo $DISPLAYdi terminal untuk memastikan tampilan Anda benar-benar :0(biasanya, tetapi tidak selalu).
Markus
Hanya ini yang bekerja untuk saya, saya menggunakan Linux Mint
Harendra Singh
5

Setidaknya untuk Ubuntu 14.04, respons klrmr di atas adalah jawaban yang benar. Tampaknya tidak perlu mengatur DISPLAY atau mengartikulasikan jalur lengkap untuk memberi tahu-kirim atau apa pun yang biasanya dalam $ PATH.

Di bawah ini adalah skrip cron yang saya gunakan untuk mematikan mesin virtual ketika kondisi baterai laptop menjadi terlalu rendah. Pengaturan baris DBUS_SESSION_BUS_ADDRESS dalam respons klrmr di atas adalah modifikasi yang akhirnya membuat peringatan bekerja dengan benar.

#!/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
sumber
Ini adalah solusi yang bekerja dengan baik untuk saya juga, saya baru saja menambahkan baris "eval ..." ke skrip saya yang saya jalankan dari crontab - sekarang berfungsi dengan baik
Mtl Dev
2

Dalam kasus saya dengan ubuntu 16.04, setiap jalur eksplisit diperlukan, saya menyelesaikan masalah hanya dengan menambahkan

DISPLAY =: 0

pada baris pertama crontab, sebelum panggilan beri tahu-kirim.

Raul R.
sumber
Ini adalah satu-satunya hal yang diperlukan untuk membuatnya bekerja pada 16.04.
Jonathan Landrum
1

Penyebab pertama adalah file crontab Anda, Anda juga harus menyebutkan nama pengguna yang dengannya skrip harus dieksekusi, lebih baik simpan sebagai root

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

dan kemudian Anda harus menggunakan nama_pengguna GUI di dalam skrip dan menambahkannya untuk memberi tahu-kirim dengan "sudo atau su" untuk menjalankan perintah sebagai pengguna yang memiliki GUI

contoh:

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

atau

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

di mana gnome_user_namenama pengguna dari pengguna yang memulai sesi GUI itu adalah Anda yang masuk, dan jika Anda ingin menjadikannya pilihan yang dinamis, Anda bisa mendapatkannya dari

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

contoh:

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

atau

sudo -u $GNOME_USER notify-send "summary" "body"
S471
sumber
1
Saya pikir ketika nama pengguna Anda lebih panjang dari karakter X, usernma Anda terpotong: Misalnya, nama pengguna saya oniltonmaciel, tetapi $GNOME_USERakan menunjukkan onilton+(tidak berfungsi)
Onilton Maciel
memperbaikinya dengan perintah yang lebih baik
S471
1

Cara biner mengambil alamat dbus tampaknya telah berubah belakangan ini. Pada Ubuntu 15.04 (Vivid Vervet) dengan "notify-send 0.7.6", diperlukan dua variabel berikut:

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

Pernyataan oleh 'krlmlr' mengevaluasi dengan baik dan menetapkan alamat yang benar, tetapi dialog tidak akan muncul dari tugas cron.

tanza
sumber
0

Jika skrip Anda di crontab berjalan sebagai root, jawaban di atas mungkin tidak akan berfungsi. Coba fungsi ini, yang berfungsi baik untuk saya di 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 
}

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

mivk
sumber
0

Lebih baik mengandalkan dbus-sessionproses, itu harus berjalan untuk semua sistem di mana DBUS_SESSION_BUS_ADDRESSada.

Buat skrip:

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

Jadikan itu dapat dieksekusi:

$ chmod +x ~/notify.sh

Tambahkan ke crontab:

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

Ini membutuhkan waktu lama untuk membuat pekerjaan di ubuntu 15.10, Harus menambahkan sumber untuk mendapatkan pengguna yang normal. tampilan saya adalah: 1 karena beberapa alasan juga. Menggunakan pid sesi pertama gnome-hasil untuk pencarian 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
sumber
0

Saya baru saja menggunakan ini untuk bekerja dengan desktop kayu manis di Ubuntu 15.10, menggunakan resep berikut:

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"

Kuncinya adalah menyadari bahwa 'sesi kayu manis' terlalu lama untuk ditemukan oleh 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

Saya juga harus menggunakan \ grep karena grep saya alias

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

Saya menggunakan i3 di Ubuntu 18.04. Cara saya untuk menyelesaikan ini adalah:

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

Tuan Goferito
sumber
0

Masalah yang disebabkan oleh panggilan python3di crontab dengan UTF-8lokal.

TL; DR: panggilan awalan di crontab dg lokal seperti pada:

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

Lihat juga klik dan 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
Stack
sumber
0

Untuk semua skrip crontab yang menggunakan libnotify, saya menggunakan ini:

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

notify_user # and do other stuff

Ia bekerja bahkan jika saya menggunakan cron dalam mode root.

azzamsa
sumber
0

Yang Anda butuhkan adalah X_user dan X_userid. Ganti keduanya dalam perintah di bawah ini.

Solusi dengan 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 file #timer

[Unit]
Description=Some desc


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

[Install]
WantedBy=list.timer.target

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

Tidak perlu menggunakan sudo -u jika file layanan sudah disetel dengan pengguna yang dituju

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

Bruno
sumber