Thông báo-gửi không hoạt động từ crontab


44

Tôi đã tạo một kịch bản sẽ thông báo cho tôi khi có một chương truyện tranh mới mà tôi đang đọc. Tôi đã sử dụng lệnh notify-send để làm điều này. Chương trình hoạt động khi tôi đang cố chạy nó trong terminal. Thông báo được hiển thị. Tuy nhiên, khi tôi đặt cái này trong crontab của mình, thông báo không hiển thị. Tôi khá chắc chắn rằng chương trình đang chạy kể từ khi tôi tạo nó để tạo một tệp cho tôi. Các tập tin đã được tạo, nhưng thông báo đã không hiển thị.

Đây là kịch bản của tôi

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

Và đây là những gì tôi đã viết trong crontab của tôi

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

Chỉ cần một lời nhắc nhở, tất cả các lệnh trong crontab cần phải có đường dẫn của chúng ở phía trước khi chúng chạy như root. Đính kèm tập lệnh và dòng trong crontab sẽ giúp ích nếu không chúng tôi chỉ đoán được vấn đề của bạn
Meer Borg

Ừ, xin lỗi. Tôi vừa làm.
dùng158335

Đây là một ý tưởng tồi. Thông báo là một thứ "GUI", cron là một thứ "console". Không có người bảo đảm rằng lib-notify sẽ có thể tìm cách hiển thị thông báo. Thay vào đó, bạn nên xem xét việc gửi dữ liệu đến thiết bị xuất chuẩn và để tin nhắn của cron đảm nhiệm việc gửi thông tin. Thông thường một email được gửi.
coteyr

2
Trong một số trường hợp, việc đặt biến HIỂN THỊ cũng có thể giúp ích, ví dụ : export DISPLAY=:0.
Glutimate

1
16.04, cái này hiệu quả với tôi */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

Câu trả lời:


18

Các lệnh cần tham chiếu vị trí của họ. Vì vậy, notify-sendcần phải được/usr/bin/notify-send

Tất cả các lệnh cần phải có đường dẫn đầy đủ của họ.

Sử dụng whereis notify-sendlệnh để xem lệnh của bạn "sống" ở đâu


2
Có bao gồm mèo, wget, nếu, let, grep, echo, vv?
dùng158335

7
Ít nhất là trên hệ thống của tôi, notify-sendlà trên PATHngay cả đối với một công việc định kỳ. Xem câu trả lời của tôi dưới đây.
krlmlr

2
Nó không phải là giải pháp cho Ubuntu 17.04. Xem askubuntu.com/a/472769/413683askubuntu.com/a/834479/413683 để thay thế.
Mateusz Piotrowski

2
Đây không phải là vấn đề. Vấn đề là các tập lệnh cron không chạy dưới phiên người dùng và không có khái niệm về môi trường của phiên đăng nhập của người dùng. Vì thông báo gửi yêu cầu kết nối với xe buýt phiên dbus để gửi thông báo, việc nhị phân được gọi từ đường nào sẽ không thành vấn đề, khi nó không kết nối với xe buýt phiên chính xác.
dobey

2
Đây KHÔNG phải là câu trả lời. Chắc chắn, nếu không thể thực thi được, nó sẽ không chạy, NHƯNG: 1. notify-send nằm trên PATH nên nó sẽ nằm ở vị trí 2. ngay cả khi nó không nằm trên PATH và bạn chỉ định đường dẫn đầy đủ nó vẫn sẽ không hoạt động, vì thực sự DBUS_SESSION_BUS_ADDRESS phải được đặt để gửi thông báo. Và câu trả lời đúng là từ kmir.
Kris Jace

31

Mọi thứ dường như khác vào ngày 13.04, ít nhất là trong Gnome Shell.

Đầu tiên, đây là những gì envin khi chạy từ zzyxycông việc định kỳ (không phải root) của người dùng :

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

Để đi notify-sendlàm, dường như cần phải đặt DBUS_SESSION_BUS_ADDRESSbiến môi trường, theo nhận xét của DahitiF trên ubuntuforums.org. Chỉ cần thêm vào sau đây để mô tả công việc thực tế của bạn:

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

Nó dường như không cần thiết để thiết lập DISPLAY.


4
Cảm ơn, đây là những gì cuối cùng đã làm việc cho tôi. Trên Xubfox, bạn phải đổi gnome-sessionsang xfce4-session.
shrx

Đây là câu trả lời duy nhất để làm việc cho 14.04, cùng với gợi ý rõ ràng của câu hỏi được chấp nhận.
Wtower

1
Tôi không có gnome-sessionvà sử dụng gnome-shellđể thay thế (cẩn thận đó cũng là một gnome-shell-calendar-serverquá pgrepsẽ nhận được 2 PID). Tôi cũng cần DISPLAY=:0vì tôi đang sử dụng 2 màn hình và nó không được xác định. Cảm ơn!
Soyuka

Nếu bạn đang sử dụng Openbox (như trên CB ++) hoán đổi openboxcho gnome-session.
ACK_stoverflow

Đây là câu trả lời đúng và câu trả lời được chấp nhận thậm chí không đúng, nó nói về biến HIỂN THỊ thậm chí không cần thiết, cũng không thực sự giải quyết được vấn đề.
Kris Jace

24

Lệnh notify-sendsẽ không hiển thị thông báo trên màn hình của bạn khi bắt đầu bằng cron. Chỉ cần thêm hiển thị mục tiêu ở đầu tập lệnh của bạn, ví dụ:

export DISPLAY=:0

Đây là những gì tôi đã phải làm trong 14.10 quá. Nếu không, tôi sẽ gặp lỗi nàygdk_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
Điều này. Và sử dụng echo $DISPLAYtrong một thiết bị đầu cuối để đảm bảo màn hình của bạn thực sự :0(thường là vậy, nhưng không phải lúc nào cũng vậy).
Đánh dấu

Chỉ điều này làm việc cho tôi, tôi đang sử dụng Linux Mint
Harendra Singh

5

Đối với Ubuntu 14.04 ít nhất, phản hồi của klrmr ở trên là câu trả lời đúng. Dường như không cần thiết phải thiết lập HIỂN THỊ hoặc chỉ rõ các đường dẫn đầy đủ để gửi thông báo hoặc bất cứ điều gì khác thường trong $ PATH.

Dưới đây là tập lệnh cron tôi đang sử dụng để tắt máy ảo khi trạng thái pin của máy tính xách tay quá thấp. Cài đặt dòng DBUS_SESSION_BUS_ADDRESS trong phản hồi của klrmr ở trên là sửa đổi cuối cùng đã có các cảnh báo hoạt động chính xác.

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

Đây cũng là giải pháp phù hợp với tôi, tôi chỉ cần thêm dòng "eval ..." vào kịch bản của mình mà tôi chạy từ crontab - bây giờ nó hoạt động hoàn hảo
Mtl Dev

2

Trong trường hợp của tôi với Ubuntu 16.04, bất kỳ đường dẫn rõ ràng nào cũng được yêu cầu, tôi giải quyết vấn đề chỉ bằng cách thêm

HIỂN THỊ =: 0

ở những dòng đầu tiên của crontab, trước khi gọi thông báo-gửi.


Đây là điều duy nhất cần thiết để làm cho nó hoạt động vào ngày 16.04.
Jonathan Landrum

1

Thủ phạm đầu tiên là tập tin crontab của bạn, bạn cũng cần đề cập đến tên người dùng mà tập lệnh phải được thực thi, tốt hơn là giữ nó dưới dạng root

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

và sau đó bạn nên sử dụng tên người dùng của người dùng GUI bên trong tập lệnh và gửi trước nó để thông báo-gửi bằng "sudo hoặc su" để thực thi lệnh với tư cách là người dùng sở hữu GUI

thí dụ :

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

hoặc là

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

nơi gnome_user_namelà tên người dùng của người dùng bắt đầu phiên GUI nó là bạn của những người đã đăng nhập, và nếu bạn muốn làm cho nó một lựa chọn động, bạn có thể lấy nó từ

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

thí dụ :

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

hoặc là

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

1
Tôi nghĩ rằng khi tên người dùng của bạn dài hơn ký tự X, usernma của bạn bị cắt ngắn: Ví dụ: tên người dùng của tôi là oniltonmaciel, nhưng $GNOME_USERsẽ hiển thị onilton+(không hoạt động)
Onilton Maciel

đã sửa nó bằng lệnh tốt hơn
S471

1

Cách thức nhị phân lấy địa chỉ dbus dường như đã thay đổi gần đây. Trên Ubuntu 15.04 (Verv Vervet) với "notify-send 0.7.6", cần có hai biến sau:

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

Tuyên bố của 'krlmlr' đánh giá tốt và đặt địa chỉ chính xác, nhưng hộp thoại sẽ không bật lên từ một công việc định kỳ.


0

Nếu tập lệnh của bạn trong crontab đang chạy bằng root, các câu trả lời ở trên có thể sẽ không hoạt động. Hãy thử chức năng này, hoạt động tốt với tôi trong 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 
}

(Nguồn: https://unix.stackexchange.com/a/344377/7286 )


0

Tốt hơn là dựa vào dbus-sessionquá trình, nó nên được chạy cho tất cả các hệ thống có DBUS_SESSION_BUS_ADDRESSmặt.

Tạo một kịch bản:

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

Làm cho nó thực thi:

$ chmod +x ~/notify.sh

Thêm nó vào crontab:

* * * * * $HOME/notify.sh

0

Điều này đã mất mãi mãi để làm việc trên Ubuntu 15.10, Phải thêm một nguồn để có được các vars env bình thường của người dùng. màn hình của tôi là: 1 vì một số lý do. Sử dụng pidome-session kết quả đầu tiên pid cho tra cứu 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

Tôi vừa có được điều này để làm việc với máy tính để bàn quế trên Ubuntu 15.10, sử dụng công thức sau:

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"

Bí quyết là nhận ra rằng 'phiên quế' quá dài để pgrep tìm thấy:

$ 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

Tôi cũng đã phải sử dụng \ grep vì grep của tôi được đặt bí danh là

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

0

Tôi sử dụng i3 trên Ubuntu 18.04. Cách của tôi để giải quyết điều này là:

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


0

Vấn đề gây ra bằng cách gọi python3trong crontab với UTF-8miền địa phương.

TL; DR: cuộc gọi tiền tố trong crontab w / locale như trong:

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

Xem thêm bấm và 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

Đối với tất cả các tập lệnh crontab sử dụng libnotify, tôi sử dụng:

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

notify_user # and do other stuff

Nó hoạt động ngay cả khi tôi sử dụng cron trong chế độ root.


0

Tất cả bạn cần là X_user và X_userid. Thay thế cả trong lệnh dưới đây.

Giải pháp với systemd

/etc/systemd/system/opreminder.service #Service tệp

[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 # Kịch bản

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

Không cần sử dụng sudo -u nếu tệp dịch vụ đã được đặt với người dùng dự định

Nguồn: https://wiki.archlinux.org/index.php/Desktop_notifying#Usage_in_programming

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.