Я написал сценарий, который должен уведомлять меня о новой главе манги, которую я читаю. Я использовал команду 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
Команды должны указывать свое местоположение. Таким образом, notify-send
должен быть / usr / bin / notify-send
Все команды должны иметь полный путь.
Используйте whereis notify-send
], чтобы увидеть, где «живут» ваши команды
Я только что получил это для работы с рабочим столом 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'
Я использую i3 в Ubuntu 18.04. Мой способ решить эту проблему:
* * * * * XDG_RUNTIME_DIR = / run / user / $ (id -u) notify-send Эй, "это собака!"
Проблема, вызванная вызовом 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
Все, что вам нужно, это X_user и X_userid. Замените оба в приведенной ниже команде.
/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
Для всех сценариев crontab, использующих libnotify, я использую следующее:
notify_user() {
local user=$(whoami)
notify-send -u normal -t 4000 "System Backup" "Starting backup"
}
notify_user # and do other stuff
Он работает, даже если я использую cron в корневом режиме.
Лучше полагаться на процесс 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
Это заняло вечность, чтобы заставить работать в 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)"
Способ получения двоичным кодом адреса dbus, похоже, в последнее время изменился. В Ubuntu 15.04 (Vivid Vervet) с «notify-send 0.7.6» необходимы следующие две переменные:
export HOME=/home/$notify_user
export DISPLAY=:0.0
Оператор 'krlmlr' оценивает нормально и устанавливает правильный адрес, но диалоговое окно не появляется из задание cron.
Первым виновником является ваш файл 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"
В моем случае с ubuntu 16.04 требовался любой явный путь, я решаю проблему, просто добавляя
DISPLAY =: 0
в первые строки crontab , перед звонком уведомить-отправить.
По крайней мере для 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
Команда notify-send
не показывала сообщение на вашем экране при запуске cron.Просто добавьте целевой экран вверху вашего скрипта, например:
export DISPLAY=:0
Все выглядит по-другому на 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
.
Если ваш скрипт в 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 )
В приведенном ниже случае я вызвал 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 в отдельный журнал.
Это заставляет его работать в 19.10:
eval "export $(pgrep -u $LOGNAME gnome-session | head -n 1 | xargs -I{} cat /proc/{}/environ | egrep -z DBUS_SESSION_BUS_ADDRESS)";
Используйте printenv
для печати переменных среды с вашего обычного терминала. А затем вставьте все переменные среды в начало файла crontab.
Решение с настройкой Дисплей =: 0,0
работал для меня в течение многих лет. В 20.04 он внезапно перестал работать. Оказалось, что теперь изменялись координаты дисплея, теперь он : 1
. Итак
export DISPLAY=:1
решил проблему.
Стайлинг всплывающего окна некрасиво, но это другая история.
Вы можете перечислить активные устройства Swap с
swapon --show
или с
cat /proc/swaps
, если вы создали файл подкачки в виде редкого файла ( https://en.wikipedia.org/wiki / Sparse_file ), возможно, что он на самом деле имеет 0 блоков, выделенных, если он никогда не был в активном использовании. Проверьте его выделенные размеры с
du -h myswapfile
и сравните с
ls -lh myswapfile
(я думаю, это то, что вы хотели достичь с этим команду filefrag -v
, которая делает что-то похожее на совпадение)
Для того, кто использует раковину рыбы , как я, вот мой сценарий, который по существу делает то же самое, что делает сценарий 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, который добавляет пути к переменной, достигают предполагаемое.