Повідомлення-відправлення не працює з crontab


44

Я створив сценарій, який повинен повідомити мене, коли з’являється нова глава манги, яку я читаю. Для цього я використовував команду notify-send. Програма працює, коли я намагаюся запустити її в терміналі. Повідомлення відображається. Однак, коли я помістив це у свій crontab, повідомлення не відображається. Я майже впевнений, що програма працює, оскільки я створив файл для мене. Файл створено, але сповіщення не відображалось.

Ось мій сценарій

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

І ось що я написав у своєму кронтабі

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

Нагадуємо, всі команди в crontab повинні мати свій шлях перед собою, коли вони виконуються як root. Додавання сценарію та рядка в crontab допоможе інакше, ми просто здогадуємось про вашу проблему
Meer Borg

Так, вибачте. Я тільки що зробив.
користувач158335

Це погана ідея. Повідомлення - це річ "GUI", cron - "консольна" річ. Немає гарантії, що lib-notify зможе знайти спосіб відображення повідомлення. Натомість слід розглянути можливість надсилання даних у stdout та дозволити повідомленням Cron піклуватися про надсилання інформації. Зазвичай надсилається електронний лист.
coteyr

2
У деяких випадках , встановлюючи змінну DISPLAY вгору може допомогти , а також, наприклад: export DISPLAY=:0.
Глутанімат

1
Бо 16.04цей працював для мене */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

Відповіді:


18

Команди повинні посилатися на своє місцезнаходження. Так notify-sendмає бути/usr/bin/notify-send

Усі команди повинні мати повний шлях.

Використовуйте whereis notify-sendкоманду, щоб побачити, де "живуть" ваші команди


2
Це включає кішку, wget, якщо, нехай, греп, ехо тощо?
користувач158335

7
Принаймні , в моїй системі, notify-sendзнаходиться на PATHнавіть хрон. Дивіться мою відповідь нижче.
krlmlr

2
Це не рішення для Ubuntu 17.04. Дивіться натомість askubuntu.com/a/472769/413683 та askubuntu.com/a/834479/413683 .
Матеуш Піотровський

2
Це не проблема. Проблема полягає в тому, що сценарії cron не виконуються під час сеансу користувача та не мають поняття про середовище сеансу входу користувача. Оскільки сповіщення-відправлення вимагає підключення до шини сеансу dbus для надсилання сповіщення, не має значення, з якого шляху викликається двійковий файл, коли він не підключається до правильної шини сеансу.
добі

2
Це НЕ відповідь. Звичайно, якщо виконуваний файл не може бути розташований, він не запуститься, АЛЕ: 1. сповіщення-відправлення є на PATH, тож воно буде розташоване 2. навіть якщо його не було на PATH, і ви вказали повний шлях, він все одно буде не працює, оскільки насправді DBUS_SESSION_BUS_ADDRESS має бути встановлено для повідомлення-відправки. І правильна відповідь - з кмр.
Кріс Джейс

31

Здається, речі 13.04 відрізняються, принаймні, у Gnome Shell.

По-перше, це те, що envдрукується під час запуску із zzyxyзавдання cron користувача (а не 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

Щоб notify-sendприступити до роботи, мабуть, потрібно встановити DBUS_SESSION_BUS_ADDRESSзмінну середовища, відповідно до коментаря DahitiF на ubuntuforums.org. Просто додайте до свого фактичного опису завдання:

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

Це, здається, не потрібно встановлювати DISPLAY.


4
Дякую, саме це нарешті спрацювало для мене. На Xubuntu вам доведеться перейти gnome-sessionна xfce4-session.
shrx

Це єдина відповідь на роботу за 14.04, разом із очевидним натяком на прийняте.
Wtower

1
Я не мав gnome-sessionі використовувати gnome-shellзамість (будьте обережні , є і gnome-shell-calendar-serverтак pgrepбуде отримати 2 ИДП). Мені це також було потрібно, DISPLAY=:0оскільки я використовую 2 фізичні екрани, і це не було визначено. Дякую!
союка

Якщо ви використовуєте Openbox (як, наприклад, у CB ++), замініть openboxна gnome-session.
ACK_stoverflow

ЦЕ є правильною відповіддю, і прийнята відповідь навіть не є правильною, вона говорить про змінну DISPLAY, яка навіть не потрібна, і вона фактично не вирішує проблему.
Кріс Джейс

24

Команда notify-sendне відображатиме повідомлення на екрані, коли запускається cron. Просто додайте цільовий дисплей у верхній частині сценарію, наприклад:

export DISPLAY=:0

Це мені довелося зробити і в 14.10. Інакше я отримав би цю помилку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:
Joelmob

1
Це. І використовуйте echo $DISPLAYв терміналі, щоб переконатися, що ваш дисплей справді є :0(як правило, але не завжди).
Марк

Тільки це працювало на мене, я використовую Linux Mint
Harendra Singh

5

Щонайменше для Ubuntu 14.04 відповідь klrmr , наведена вище, є правильною відповіддю. Здається, не потрібно встановлювати DISPLAY або сформулювати повні шляхи для повідомлення-відправки або нічого іншого, як правило, у $ PATH.

Нижче наводиться сценарій cron, який я використовую для відключення віртуальної машини, коли стан акумулятора ноутбука стає занадто низьким. Налаштування рядка DBUS_SESSION_BUS_ADDRESS у відповіді klrmr вище - це модифікація, яка остаточно отримала попередження правильно.

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

Це рішення, яке чудово працювало і для мене, я просто додав рядок "eval ..." до свого сценарію, який запускаю з crontab - зараз він ідеально працює
Mtl Dev

2

У моєму випадку з ubuntu 16.04 потрібен будь-який явний шлях, я вирішую проблему лише додаючи

ДИСПЛЕЙ =: 0

на перших рядках crontab, перед тим як дзвінок сповістити-надіслати.


Це єдине, що потрібно, щоб він працював 16.04.
Джонатан Ландрум

1

Перший винуватець - ваш файл crontab, вам також потрібно згадати ім'я користувача, з яким має виконуватися сценарій, краще зберегти його як root

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

а потім слід використовувати ім'я користувача користувача GUI всередині скрипту та додати його до сповіщення-надсилання із "sudo or su", щоб виконати команду як користувач, якому належить графічний інтерфейс.

приклад:

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

або

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

де gnome_user_nameім’я користувача, який розпочав сеанс GUI, це ви ввійшли в систему, і якщо ви хочете зробити це динамічним вибором, ви можете отримати його від

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

приклад:

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

або

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

1
Я думаю, що коли ваше ім’я користувача більше, ніж X символів, ваше користувальницьке врізане: Наприклад, моє ім’я користувача є oniltonmaciel, але воно $GNOME_USERвідображатиметься onilton+(не працює)
Onilton Maciel

виправлено це з кращою командою
S471

1

Спосіб, яким двійковий файл отримує адресу dbus, здається, змінився останнім часом. Для Ubuntu 15.04 (Vivid Vervet) з "notify-send 0.7.6" потрібні наступні дві змінні:

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

Заява 'krlmlr' оцінює штраф і встановлює правильну адресу, але діалогове вікно не вискочить із завдання cron.


0

Якщо ваш скрипт у crontab працює як root, відповіді вище, ймовірно, не спрацюють. Спробуйте цю функцію, яка добре працює для мене 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 
}

(Джерело: https://unix.stackexchange.com/a/344377/7286 )


0

Краще покладатися на dbus-sessionпроцес, він повинен працювати для всіх систем, де DBUS_SESSION_BUS_ADDRESSє.

Створіть сценарій:

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

Зробіть його виконуваним:

$ chmod +x ~/notify.sh

Додайте його до crontab:

* * * * * $HOME/notify.sh

0

Це зайняло назавжди, щоб зробити роботу над ubuntu 15.10. Довелося додати джерело, щоб користувачі нормально діставались до навколишнього середовища. мій показ був: 1 також чомусь. Використання gidome сеансу перших результатів для пошуку 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

Щойно я отримав це для роботи з коричним робочим столом на Ubuntu 15.10, використовуючи наступний рецепт:

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"

Хитрість полягала в тому, щоб зрозуміти, що «сеанс кориці» занадто довгий, щоб знайти 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

Я також повинен був використовувати \ grep, тому що мій греп відчужений

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

0

Я використовую i3 на Ubuntu 18.04. Мій спосіб вирішити це:

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


0

Проблема, викликана викликом python3у crontab з UTF-8locale.

TL; DR: виклик префікса в crontab w / locale як у:

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

Дивіться також клік та 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

Для всіх скриптів crontab, які використовують libnotify, я використовую це:

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

notify_user # and do other stuff

Він працює, навіть якщо я використовую cron в кореневому режимі.


0

Все, що вам потрібно, це X_user і X_userid. Замініть обидва в командному рядку.

Рішення з systemd

/etc/systemd/system/opreminder.service # файл сервісу

[Unit]
Descrption=some service to run

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


/etc/systemd/system/opreminder.timer #timer файл

[Unit]
Description=Some desc


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

[Install]
WantedBy=list.timer.target

/home/jchester/bin/opreminder.sh # Сценарій

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

Не потрібно використовувати sudo -u, якщо сервісний файл уже встановлений із призначеним користувачем

Джерело: https://wiki.archlinux.org/index.php/Desktop_notifications#Usage_in_programming

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.