Menggunakan notify-send with cron

32

Saya menggunakan Arch Linux dengan KDE / Awesome WM. Saya mencoba untuk mulai notify-sendbekerja cron.

Saya telah mencoba pengaturan DISPLAY/ XAUTHORITYvariabel, dan berjalan notify-senddengan "sudo -u", semuanya tanpa hasil.

Saya dapat memanggil notify-send secara interaktif dari sesi dan mendapatkan notifikasi.

FWIW, pekerjaan cron berjalan dengan baik yang saya verifikasi dengan menggemakan hal ke file sementara. Hanya "kirim-kirim" yang gagal berfungsi.

Kode:

[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 ~]$ 

Seperti yang Anda lihat gema sebelum & sesudah pemberitahuan-kirim bekerja.
Saya juga telah mencoba pengaturanDISPLAY=:0.0

UPDATE: Saya mencari sedikit lebih banyak dan menemukan bahwa DBUS_SESSION_BUS_ADDRESS perlu disetel. Dan setelah hardcoding ini menggunakan nilai yang saya dapatkan dari sesi interaktif saya, pesan "halo" kecil mulai muncul di layar setiap menit!

Tetapi hasil tangkapannya adalah variabel ini tidak permanen untuk setiap pos tersebut, jadi saya akan mencoba solusi pipa yang disarankan di sana.

[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

Karena cronsepertinya tidak mendukung notify-send (setidaknya tidak secara langsung) apakah ada beberapa sistem notifikasi lain yang lebih cronramah yang dapat saya gunakan?

hanya seseorang
sumber
Ini harus bekerja sejauh yang saya bisa lihat. Mengapa Anda tidak menambahkan &>>/tmp/crontestke baris kirim pemberitahuan dan lihat apakah notify-sendada pesan kesalahan.
Graeme
Karena penasaran, apakah Anda mencoba solusi saya? Tampaknya jauh lebih sederhana dan bekerja dengan baik pada Debian saya. Saya hanya ingin tahu apakah itu Debian spesifik atau tidak
terdon
@terdon Saya mencoba solusi Anda (hanya tes cepat) dan tampaknya berfungsi pada sistem Debian saya. Saya ingin tahu apakah ini berlaku secara umum karena memang lebih sederhana.
Marco
@ Mars saya menggunakan LMDE (dasarnya pengujian Debian) dan menggunakan Cinnamon sebagai DE. Tidak dapat memberi tahu Anda jika berhasil di luar itu.
terdon
@Marco & terdon: Orang-orang Ubuntu dapat melakukannya: ubuntuforums.org/showthread.php?t=1727148
justsomeone

Jawaban:

29

Anda perlu mengatur DBUS_SESSION_BUS_ADDRESSvariabel. Secara default cron tidak memiliki akses ke variabel. Untuk mengatasinya, letakkan skrip berikut di suatu tempat dan panggil ketika pengguna masuk, misalnya menggunakan fungsi luar biasa dan yang run_oncedisebutkan di wiki. Metode apa pun akan dilakukan, karena tidak ada salahnya jika fungsi dipanggil lebih sering dari yang dibutuhkan.

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

Ini membuat file yang berisi variabel lingkungan Dbus yang diperlukan. Kemudian dalam skrip bernama cron Anda mengimpor variabel dengan sumber skrip:

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

Ini jawaban yang menggunakan mekanisme yang sama.

Marco
sumber
1
Senang melihat bahwa saya hampir mendekati solusinya. Terima kasih Marco, itu rapi!
justsomeone
Hebat, saya menggunakan kembali jawaban Anda dan menambahkan beberapa instruksi lebih rinci di sini: askubuntu.com/a/537721/34298
rubo77
Bukankah ini risiko keamanan? security.stackexchange.com/questions/71019/...
rubo77
@Gilles Bagaimana Anda bisa melakukan ini dalam satu baris seperti yang Anda sebutkan dalam obrolan?
rubo77
Saya telah mencoba begitu banyak jawaban lain tidak termasuk DBUS di ubuntu 15.10 dan tidak ada yang berhasil. Yang itu sederhana dan bekerja dengan sempurna.
bastian
16

Anda perlu mengatur variabel di crontab itu sendiri:

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

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

Tidak sudodiperlukan, setidaknya tidak pada sistem saya.

terdon
sumber
Terima kasih terdon atas waktu Anda. Ini tampaknya menjadi solusi sederhana. Sayangnya, ini tidak berhasil untuk saya,
justsomeone
@ hanya seseorang ya, mungkin tergantung pada lingkungan desktop.
terdon
Saya pikir ini ada hubungannya dengan distro atau Lingkungan Desktop. Untuk pengguna Ubuntu, solusi langsung tampaknya bekerja dengan baik dari apa yang saya lihat di forum online.
justsomeone
@ justsomeone Saya menggunakan Debian (LMDE) menggunakan Kayu Manis sebagai DE. Mungkin ada hubungannya dengan bagaimana X dimulai atau dengan sistem notifikasi yang digunakan oleh DE, tak tahu.
terdon
Dikonfirmasi itu berfungsi di Ubuntu 14.04 / 14.10. Dengan GNOME dan Unity.
Jordon Bedwell
8

Cara paling aman untuk mendapatkan variabel lingkungan terkait sesi X adalah dengan mendapatkannya dari lingkungan proses pengguna yang masuk ke X. Ini adalah adaptasi dari skrip yang saya gunakan untuk tujuan yang persis sama (meskipun DBUS_SESSION_BUS_ADDRESS tidak t tampaknya menjadi masalah bagi saya di 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"

Ini mengirim pesan ke pengguna X pertama yang ditemukannya, meskipun Anda bisa menambahkan loop untuk mengirimkannya ke semua pengguna.

Memperbarui

Tampaknya pembaruan ke format utmp menyebabkan whountuk mencetak tampilan daripada tty di kolom kedua. Ini sebenarnya membuat segalanya lebih mudah, sebelumnya hanya mencetak tampilan di komentar di akhir dan saya memutuskan ini tidak aman untuk diandalkan untuk jawaban yang asli. Jika ini masalahnya, coba ini:

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
sumber
Ini tidak berfungsi untuk saya di Trusty karena tidak ada tty yang dicetak dalam who_lineperintah. Outputnya seperti me :0 2015-09-23 10:40 ? 17234.
blujay
1
@blujay, diperbarui.
Graeme
Terima kasih, itu berhasil. Namun, ketika saya memposting dalam jawaban terpisah, ada solusi yang bahkan lebih sederhana.
blujay
@blujay ya, ini merupakan upaya jawaban portabel. Tidak yakin ini benar-benar mungkin, tetapi masih harus bekerja dalam kebanyakan kasus.
Graeme
2

One-liner ini bekerja untuk saya di Manjaro dengan 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.'

Tanpa DBUS_blah_blah yang sangat jelek itu tidak akan berfungsi sama sekali. Saya juga menemukan journalctl -xb -u croniebermanfaat. Saya belum terbiasa dengan Cronie, tetapi membuat "crontab" /etc/cron.d/mycronjobssaya dan saya tidak yakin apakah nama file itu diperlukan, atau apakah hanya membaca semua yang ada di direktori cron.d.

Saya menemukan solusinya di sini https://wiki.archlinux.org/index.php/Desktop_notifications

PJ Brunet
sumber
2

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
1

Ini cukup untuk membuat pekerjaan kirim pemberitahuan untuk saya di cronjob di Ubuntu Trusty:

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

Ini hanya mengekspor DISPLAYuntuk pengguna yang menjalankan cronjob. Ini berfungsi untuk saya tanpa pengaturan XAUTHORITYatau DBUS_SESSION_BUS_ADDRESS.

blujay
sumber
1
Berfungsi di Ubuntu 16.04 juga. Saya sebenarnya memiliki cron yang meluncurkan skrip Perl, yang system () adalah skrip bash, yang meluncurkan skrip Perl yang berbeda, yang menjalankan sistem ("notify-send ..."). Menambahkan perintah ekspor ke skrip bash memodifikasi lingkungan skrip tersebut, yang kemudian mewariskan skrip Perl yang lalu dan menyediakannya ke sistem ("notify-send ..."). Bagus temukan blujay!
Tim
1

Bagi mereka yang di Linux yang nyaman menginstal paket Python, saya baru saja merilis program notify-send-headless yang berfungsi baik untuk saya. Ini mencari /procvariabel nama pengguna dan lingkungan yang diperlukan dan kemudian berjalan notify-senddengan variabel-variabel ini (akan digunakan sudountuk beralih ke pengguna yang diperlukan jika perlu).

xolox
sumber
1

Anda juga dapat membuat skrip:

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

Kemudian jalankan dengan sudo. Namun, karena crontab -emenjalankan semua perintah dengan pengguna yang membuatnya, berikut ini sudah cukup ketika dipanggil tanpa sudo:

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

Setidaknya itu untuk saya. Itu semua tampaknya tergantung pada konfigurasi lingkungan.

pengguna1112789
sumber
0

Saya menggunakan skrip ini di cron untuk mengirim MPD yang sekarang diputar ke twitter setiap jam

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

skrip serupa menggunakan notify-send

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

Anda mungkin mengalami masalah karena KDE menggunakan notify-deamon IIRC miliknya sendiri.

awan tipis
sumber
0

Untuk apa nilainya ....

Saya harus menggunakan SEMUA hal berikut di Debian Jessie untuk membuatnya berfungsi ...

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

Meninggalkan salah satu dari ini menyebabkannya berhenti bekerja.

BenJ
sumber
Baris terakhir itu tidak akan melakukan apa pun seperti yang ditulis di sini, karena tidak akan ada file yang secara harfiah dipanggil *-0di session-busdirektori Anda . Anda mungkin berarti source "$HOME"/.dbus/session-bus/*-0.
roaima
0

Menggunakan sudo:

sudo -u $currentxuser notify-send $message

Kiat:

Kita bisa mendapatkan pengguna x saat ini dengan perintah ini

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

Tambahan...

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

Senang mendengarnya :

Cron yang berjalan di bawah root tidak memiliki akses ke x sehingga semua perintah gui tidak akan ditampilkan, salah satu solusi sederhana adalah menambahkan root ke pengguna x yang diotorisasi untuk pengguna x saat ini dengan perintah ini

dari shell pengguna x

xhost local:root

atau

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

Berikut ini skrip yang tidak terlalu rumit daripada yang disediakan Graeme. Naskahnya tidak berfungsi untuk saya, $who_lineselalu kosong. Script saya tidak membuang banyak waktu untuk menemukan suatu proses. Sebagai gantinya, ia hanya mencoba semua dan memilih nilai berguna terakhir yang ditemukan. Saya menjalankan xubuntu 14.04 dan menjalankan beberapa wadah lxc yang mungkin membingungkan skrip semacam ini.

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
sumber
Ini tidak berfungsi untuk saya di Trusty karena lingkungan proses Xorg tidak punya DBUS_SESSION_BUS_ADDRESS. Saya bisa mendapatkannya dari kulit saya, tetapi tidak dari proses Xorg.
blujay