Sử dụng thông báo-gửi với cron


32

Tôi đang sử dụng Arch Linux với KDE / Awesome WM. Tôi đang cố gắng notify-sendđể làm việc với cron.

Tôi đã thử cài đặt DISPLAY/ XAUTHORITYbiến và chạy notify-sendvới "sudo -u", tất cả đều không có kết quả.

Tôi có thể gọi thông báo-gửi tương tác từ phiên và nhận thông báo.

FWIW, công việc định kỳ đang chạy tốt mà tôi đã xác minh bằng cách lặp lại nội dung vào một tệp tạm thời. Nó chỉ là "thông báo gửi" không hoạt động.

Mã số:

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

Như bạn có thể thấy tiếng vang trước & sau khi thông báo-gửi làm việc.
Ngoài ra tôi đã thử cài đặtDISPLAY=:0.0

CẬP NHẬT: Tôi đã tìm kiếm thêm một chút và thấy rằng DBUS_SESSION_BUS_ADDRESS cần được đặt. Và sau khi mã hóa điều này bằng cách sử dụng giá trị tôi nhận được từ phiên tương tác của mình, thông báo "xin chào" nhỏ bé bắt đầu xuất hiện trên màn hình mỗi phút!

Nhưng điều đáng chú ý là biến này không phải là vĩnh viễn trên mỗi bài đăng đó, vì vậy tôi sẽ thử giải pháp đường ống có tên được đề xuất ở đó.

[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

crondường như không hỗ trợ gửi thông báo (ít nhất là không trực tiếp), có một số hệ thống thông báo khác cronthân thiện hơn mà tôi có thể sử dụng không?


Điều này sẽ làm việc như xa như tôi có thể nhìn thấy. Tại sao bạn không thêm một &>>/tmp/crontestdòng gửi thông báo và xem nếu notify-sendđưa ra bất kỳ thông báo lỗi nào.
Graeme

Vì tò mò, bạn đã thử giải pháp của tôi chưa? Nó có vẻ đơn giản hơn nhiều và hoạt động hoàn hảo trên Debian của tôi. Tôi chỉ hỏi để biết nó có cụ thể về Debian hay không
terdon

@terdon Tôi đã thử giải pháp của bạn (chỉ là một thử nghiệm nhanh) và nó dường như hoạt động trên hệ thống Debian của tôi. Tôi muốn biết nếu nó thường được áp dụng vì nó thực sự đơn giản hơn.
Marco

@Marco Tôi đang dùng LMDE (về cơ bản là kiểm tra Debian) và sử dụng Cinnamon làm DE. Không thể cho bạn biết nếu nó hoạt động ngoài những người đó.
terdon

@Marco & terdon: Các chàng trai Ubuntu có thể làm như vậy: ubuntuforums.org/showthread.php?t=1727148
jowersomeone

Câu trả lời:


29

Bạn cần đặt DBUS_SESSION_BUS_ADDRESSbiến. Theo mặc định, cron không có quyền truy cập vào biến. Để khắc phục điều này, hãy đặt đoạn mã sau vào một nơi nào đó và gọi nó khi người dùng đăng nhập, ví dụ như sử dụng awesomerun_oncechức năng được đề cập trên wiki. Bất kỳ phương pháp nào cũng được, vì nó không gây hại nếu hàm được gọi thường xuyên hơn mức yêu cầu.

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

Điều này tạo ra một tệp chứa biến Diron evironment cần thiết. Sau đó, trong tập lệnh được gọi bởi cron, bạn nhập biến bằng cách tìm nguồn cho tập lệnh:

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

Đây là một câu trả lời sử dụng cơ chế tương tự.


1
Vui mừng khi thấy rằng tôi đã gần đến giải pháp. Cảm ơn Marco, đó là gọn gàng!
jowersomeone

Thật tuyệt, tôi đã sử dụng lại câu trả lời của bạn và thêm một số hướng dẫn chi tiết hơn tại đây: askubfox.com/a/537721/34298
rubo77

Đây sẽ không phải là một rủi ro bảo mật? security.stackexchange.com/questions/71019/
hàn

@Gilles Làm thế nào bạn có thể làm điều này trong một dòng như bạn đã đề cập trong trò chuyện?
rubo77

Tôi đã thử rất nhiều câu trả lời khác, không bao gồm DBUS trên Ubuntu 15.10 và không có gì hoạt động. Đó là một trong những đơn giản và làm việc hoàn hảo.
bastian

16

Bạn cần đặt các biến trong chính crontab:

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

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

Không sudocần thiết, ít nhất là không phải trên hệ thống của tôi.


Cảm ơn terdon cho thời gian của bạn. Đây dường như là một giải pháp đơn giản. Thật không may, điều này không làm việc cho tôi,
jowersomeone

@jowersomeone huh, OK, có thể phụ thuộc vào môi trường máy tính để bàn rồi.
terdon

Tôi nghĩ rằng điều này có liên quan đến distro hoặc Desktop Môi trường. Đối với người dùng Ubuntu, các giải pháp chuyển tiếp thẳng dường như hoạt động tốt từ những gì tôi đã thấy trên các diễn đàn trực tuyến.
jowersomeone

@jowersomeone Tôi đang sử dụng Debian (LMDE) bằng cách sử dụng Cinnamon làm DE. Có thể có một cái gì đó để làm với cách X được bắt đầu hoặc với hệ thống thông báo được sử dụng bởi DE, dunno.
terdon

Xác nhận nó hoạt động trên Ubuntu 14.04 / 14.10. Với Gnome và Unity.
Jordon Bedwell

8

Cách an toàn nhất để có được các biến môi trường liên quan đến phiên X là lấy chúng từ môi trường của một quá trình người dùng đã đăng nhập vào X. Đây là bản điều chỉnh của tập lệnh mà tôi sử dụng cho cùng một mục đích (mặc dù DBUS_SESSION_BUS_ADDRESS không ' Có vẻ như là một vấn đề đối với tôi trên 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"

Điều này sẽ gửi tin nhắn đến người dùng X đầu tiên mà nó tìm thấy, mặc dù bạn có thể thêm một vòng lặp để gửi nó cho tất cả người dùng.

Cập nhật

Có vẻ như các bản cập nhật cho định dạng utmp gây ra whoviệc in một màn hình thay vì một tty trong cột thứ hai của nó. Điều này thực sự làm cho mọi thứ dễ dàng hơn, trước đây nó chỉ in màn hình trong phần bình luận ở cuối và tôi quyết định điều này không an toàn khi dựa vào câu trả lời ban đầu. Nếu đây là trường hợp, hãy thử điều này:

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"

Điều này không phù hợp với tôi trên Trusty vì không có who_linelệnh in nào trong lệnh. Đầu ra trông như thế me :0 2015-09-23 10:40 ? 17234.
blujay

1
@blujay, cập nhật.
Graeme

Cảm ơn, điều đó làm việc. Tuy nhiên, như tôi đã đăng trong một câu trả lời riêng biệt, có một giải pháp thậm chí còn đơn giản hơn.
blujay

@blujay yeah, đây là một nỗ lực cho một câu trả lời di động. Không chắc chắn điều này thực sự có thể mặc dù, nhưng nó vẫn sẽ hoạt động trong hầu hết các trường hợp.
Graeme

2

Điều này đã làm việc cho tôi ở Manjaro với 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.'

Nếu không có DBUS_blah_blah rất xấu thì nó hoàn toàn không hoạt động. Tôi cũng thấy journalctl -xb -u croniehữu ích. Tôi chưa quen với Cronie, nhưng tôi đã tạo "crontab" của mình /etc/cron.d/mycronjobsvà tôi không chắc tên tập tin đó có bắt buộc không, hoặc nếu nó chỉ đọc mọi thứ trong thư mục cron.d.

Tôi đã tìm thấy giải pháp tại đây https://wiki.archlinux.org/index.php/Desktop_notifying


2

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


1

Điều này là đủ để thực hiện công việc gửi thông báo cho tôi trong một cronjob trên Ubuntu Trusty:

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

Nó chỉ đơn giản là xuất khẩu DISPLAYcho người dùng mà cronjob đang chạy. Nó hoạt động cho tôi mà không cần thiết lập XAUTHORITYhoặc DBUS_SESSION_BUS_ADDRESS.


1
Hoạt động trên Ubuntu 16.04 là tốt. Tôi thực sự có cron khởi chạy một tập lệnh Perl, tập lệnh hệ thống () sa bash, tập lệnh này khởi chạy một tập lệnh Perl khác, thực hiện một hệ thống ("notify-send ..."). Việc thêm lệnh xuất vào tập lệnh bash đã sửa đổi môi trường cho tập lệnh đó, tập lệnh Perl cuối cùng được kế thừa và cung cấp cho hệ thống ("notify-send ..."). Tốt tìm blujay!
Tim

1

Đối với những người dùng Linux thoải mái cài đặt các gói Python, tôi vừa phát hành một chương trình không gửi thông báo đang hoạt động tốt cho tôi. Nó tìm kiếm /proctên người dùng và biến môi trường cần thiết và sau đó chạy notify-sendvới các biến này (nó sẽ sử dụng sudođể chuyển sang người dùng được yêu cầu nếu cần thiết).


1

Bạn cũng có thể tạo một kịch bản:

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

Sau đó chạy nó với sudo. Tuy nhiên, vì crontab -echạy tất cả các lệnh với người dùng đã tạo ra nó, nên sau đây sẽ đủ khi được gọi mà không có sudo:

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

Ít nhất nó có nghĩa với tôi. Tất cả dường như phụ thuộc vào cấu hình môi trường.


0

Tôi sử dụng tập lệnh này trong cron để đăng MPD hiện đang phát lên twitter mỗi giờ

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

kịch bản tương tự bằng cách sử dụng thông báo-gửi

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

bạn có thể đang gặp vấn đề vì KDE sử dụng IIRC thông báo riêng của mình.


0

Cho những gì nó có giá trị....

Tôi đã phải sử dụng TẤT CẢ những điều sau đây trên Debian Jessie để làm việc này ...

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

Để lại bất kỳ một trong số này làm cho nó ngừng hoạt động.


Dòng cuối cùng đó sẽ không làm bất cứ điều gì như được viết ở đây, bởi vì sẽ không có tệp nào được gọi *-0theo nghĩa đen trong session-busthư mục của bạn . Bạn có thể có ý nghĩa source "$HOME"/.dbus/session-bus/*-0.
roaima

0

Sử dụng sudo:

sudo -u $currentxuser notify-send $message

Tiền boa :

Chúng ta có thể có được người dùng x hiện tại bằng lệnh này

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

Ngoài ra...

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

Điều tốt để biết:

Cron chạy dưới root không có quyền truy cập vào x do đó tất cả các lệnh gui sẽ không được hiển thị, một giải pháp đơn giản là thêm root cho người dùng x được ủy quyền cho người dùng x hiện tại bằng lệnh này

từ vỏ người dùng x

xhost local:root

hoặc là

sudo -u $currentxuser xhost local:root

-1

Đây là một kịch bản ít phức tạp hơn những gì Graeme cung cấp. Kịch bản của anh ấy không làm việc cho tôi, $who_lineluôn trống rỗng. Kịch bản của tôi không lãng phí quá nhiều thời gian với việc tìm kiếm một quy trình. Thay vào đó, nó chỉ thử tất cả và chọn giá trị hữu ích cuối cùng được tìm thấy. Tôi đang chạy xubfox 14.04 và có một số container lxc đang chạy có thể gây nhầm lẫn loại kịch bản này.

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"

Điều này không phù hợp với tôi trên Trusty vì môi trường của quy trình Xorg không có DBUS_SESSION_BUS_ADDRESS. Tôi có thể lấy nó từ vỏ của mình, nhưng không phải từ quy trình Xorg.
blujay
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.