Уведомление-отправка не работает из crontab

Я написал сценарий, который должен уведомлять меня о новой главе манги, которую я читаю. Я использовал команду 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

А вот что я написал в моем crontab

0,15,30,45 12-23 * * 3   /home/jchester/bin/opreminder.sh
58
задан 10 October 2016 в 15:08

20 ответов

Команды должны указывать свое местоположение. Таким образом, notify-send должен быть / usr / bin / notify-send

Все команды должны иметь полный путь.

Используйте whereis notify-send ], чтобы увидеть, где «живут» ваши команды

20
ответ дан 10 October 2016 в 15:08

Я только что получил это для работы с рабочим столом cinnamon в 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"

Уловка заключалась в том, чтобы понять, что «сеанс cinnamon-session» слишком длинный чтобы найти 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, потому что мой grep имеет псевдоним

$ alias grep
alias grep='grep -n --color=always'
0
ответ дан 10 October 2016 в 15:08

Я использую i3 в Ubuntu 18.04. Мой способ решить эту проблему:

* * * * * XDG_RUNTIME_DIR = / run / user / $ (id -u) notify-send Эй, "это собака!"

2
ответ дан 10 October 2016 в 15:08

Проблема, вызванная вызовом python3 в crontab с локалью UTF-8 .

TL; DR: вызов префикса в crontab w / locale как в:

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

См. также click и 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
ответ дан 10 October 2016 в 15:08

Все, что вам нужно, это X_user и X_userid. Замените оба в приведенной ниже команде.

Решение с помощью 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 # Сценарий

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

0
ответ дан 10 October 2016 в 15:08

Для всех сценариев 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
ответ дан 10 October 2016 в 15:08

Лучше полагаться на процесс 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
ответ дан 10 October 2016 в 15:08

Это заняло вечность, чтобы заставить работать в Ubuntu 15.10. Пришлось добавить источник, чтобы пользователи могли получить обычные переменные окружения. мой дисплей тоже по какой-то причине был: 1. Использование gnome-session first pid для поиска 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)"
2
ответ дан 10 October 2016 в 15:08

Способ получения двоичным кодом адреса dbus, похоже, в последнее время изменился. В Ubuntu 15.04 (Vivid Vervet) с «notify-send 0.7.6» необходимы следующие две переменные:

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

Оператор 'krlmlr' оценивает нормально и устанавливает правильный адрес, но диалоговое окно не появляется из задание cron.

1
ответ дан 10 October 2016 в 15:08

Первым виновником является ваш файл crontab, вам также необходимо указать имя пользователя, с которым должен запускаться скрипт, лучше оставить его как root

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

, а затем вы должны использовать имя пользователя GUI внутри скрипта и добавьте его к уведомлению-отправке с помощью «sudo или su» для выполнения команды от имени пользователя, владеющего графическим интерфейсом

, пример:

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

или

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

, где gnome_user_name - имя пользователя, который начал сеанс графического интерфейса это вы вошли в систему, и если вы хотите сделать его динамическим выбором, вы можете получить его из примера

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
ответ дан 10 October 2016 в 15:08

В моем случае с ubuntu 16.04 требовался любой явный путь, я решаю проблему, просто добавляя

DISPLAY =: 0

в первые строки crontab , перед звонком уведомить-отправить.

3
ответ дан 10 October 2016 в 15:08

По крайней мере для 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
6
ответ дан 10 October 2016 в 15:08

Команда notify-send не показывала сообщение на вашем экране при запуске cron.Просто добавьте целевой экран вверху вашего скрипта, например:

export DISPLAY=:0
27
ответ дан 10 October 2016 в 15:08

Все выглядит по-другому на 13. 04, по крайней мере, в Gnome Shell.

Во-первых, это то, что env печатает при запуске из задания cron пользователя zzyxy (не корневого):

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's на ubuntuforums. орг. Просто представьте следующее к вашему реальному описанию задания:

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

Кажется, нет необходимости устанавливать DISPLAY.

39
ответ дан 10 October 2016 в 15:08

Если ваш скрипт в 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
ответ дан 10 October 2016 в 15:08

В приведенном ниже случае я вызвал notify-send из сценария python, который отслеживает память процессов, поскольку у меня возникли проблемы с ростом памяти XOrg.

Пример ниже должен работать и не выводит предупреждение : подстановка команды: игнорируется нулевой байт на входе предупреждение.

myscript_cron.sh:

#!/bin/bash
echo $0 called: `date`
export USER=`whoami`
export HOME=/home/$USER
export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u ${USER} gnome-session | head -n 1)/environ | tr '\0' '\n'| sed 's/DBUS_SESSION_BUS_ADDRESS=//')

cd <path_to_my_script>

/usr/bin/python3.7 ./<my_script>.py 2>&1 1>/dev/null

crontab:

Примечание: запускается как crontab -e в моей учетной записи пользователя, а не sudo

* * * * * <path_to_my_script>/myscript_cron.sh  >> <path_to_my_script>/cron.log 2>&1

Мне нравится отслеживать вывод вызовов cron в файл журнала, чтобы я мог отлаживать сценарий оболочки, но я не хочу, чтобы он был загрязнен stdout скрипта Python. Я вывожу сценарий python в отдельный журнал.

0
ответ дан 5 January 2021 в 23:23

Это заставляет его работать в 19.10:

eval "export $(pgrep -u $LOGNAME gnome-session | head -n 1 | xargs -I{} cat /proc/{}/environ | egrep -z DBUS_SESSION_BUS_ADDRESS)";
0
ответ дан 5 January 2021 в 23:23

Используйте printenv для печати переменных среды с вашего обычного терминала. А затем вставьте все переменные среды в начало файла crontab.

1
ответ дан 5 January 2021 в 23:23

Решение с настройкой Дисплей =: 0,0 работал для меня в течение многих лет. В 20.04 он внезапно перестал работать. Оказалось, что теперь изменялись координаты дисплея, теперь он : 1 . Итак

export DISPLAY=:1

решил проблему.

Стайлинг всплывающего окна некрасиво, но это другая история.

0
ответ дан 2 April 2021 в 01:12

Вы можете перечислить активные устройства Swap с

swapon --show

или с

cat /proc/swaps

, если вы создали файл подкачки в виде редкого файла ( https://en.wikipedia.org/wiki / Sparse_file ), возможно, что он на самом деле имеет 0 блоков, выделенных, если он никогда не был в активном использовании. Проверьте его выделенные размеры с

du -h myswapfile

и сравните с

ls -lh myswapfile

(я думаю, это то, что вы хотели достичь с этим команду filefrag -v , которая делает что-то похожее на совпадение)

-121 908755-

Для того, кто использует раковину рыбы , как я, вот мой сценарий, который по существу делает то же самое, что делает сценарий Bash @ Denis.peplin. Я использую его для отправки предупреждения, когда заряд батареи низкий.

#!/bin/fish

# set environment variables
pidof dbus-daemon | tr ' ' '\n' | while read -l pid
        set environs $environs /proc/$pid/environ
end
set -x DBUS_SESSION_BUS_ADDRESS (cat $environs 2>/dev/null | tr '\0' '\n' | grep DBUS_SESSION_BUS_ADDRESS>
set -x DISPLAY :0

# perform actual job
set capacity (cat /sys/class/power_supply/BAT0/capacity)
if test $capacity -le $argv[1]
        /usr/local/bin/dunstify -u critical -t 10000 "Battery low!" "Plug in asap."
end

Мне пришлось избегать awk , потому что его тип возврата представляет собой строку, содержащую два пути, которые разделены пространством. Переменная рыбы не извлекает два пути, но хранит всю строку, вызывая конфликты при использовании Cat $ EnviRons . Используя цикл While, который добавляет пути к переменной, достигают предполагаемое.

0
ответ дан 2 April 2021 в 01:12

Другие вопросы по тегам:

Похожие вопросы: