将通知发送与 cron 一起使用

jus*_*one 40 shell scripting cron libnotify

我正在使用带有 KDE/Awesome WM 的 Arch Linux。我正在尝试 notify-sendcron.

我试过设置DISPLAY/XAUTHORITY变量,并notify-send使用“sudo -u”运行,但都没有结果。

我能够从会话中以交互方式调用通知发送并获取通知。

FWIW,cron 作业运行良好,我通过将内容回显到临时文件进行了验证。只是“通知发送”不起作用。

代码:

[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 ~]$ 
Run Code Online (Sandbox Code Playgroud)

如您所见,通知发送之前和之后的回声有效。
我也试过设置DISPLAY=:0.0

更新:我搜索了一些,发现需要设置DBUS_SESSION_BUS_ADDRESS。在使用我从交互式会话中获得的值对其进行硬编码后,屏幕上每分钟都会弹出一个小小的“你好”消息!

但问题是这个变量不是永久的,所以我会尝试那里建议的命名管道解决方案。

[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
Run Code Online (Sandbox Code Playgroud)

由于cron似乎不支持通知发送(至少不直接),是否还有其他一些更cron友好的通知系统可以使用?

Mar*_*rco 39

您需要设置DBUS_SESSION_BUS_ADDRESS变量。默认情况下,cron 无权访问该变量。为了解决这个问题,将以下脚本放在某处并在用户登录时调用它,例如使用awesomerun_oncewiki 上提到的功能。任何方法都可以,因为如果函数被调用的次数超过所需的次数,也不会造成损害。

#!/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
Run Code Online (Sandbox Code Playgroud)

这将创建一个包含所需 Dbus 环境变量的文件。然后在 cron 调用的脚本中,通过获取脚本来导入变量:

if [ -r "$HOME/.dbus/Xdbus" ]; then
  . "$HOME/.dbus/Xdbus"
fi
Run Code Online (Sandbox Code Playgroud)

这是使用相同机制的答案。

  • 很高兴看到我几乎接近解决方案。谢谢马可,那很好! (2认同)

ter*_*don 18

您需要在 crontab 本身中设置变量:

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

# m h  dom mon dow   command 
* * * * *  /usr/bin/notify-send "hello"
Run Code Online (Sandbox Code Playgroud)

不需要sudo,至少在我的系统上不需要。


Gra*_*eme 7

获取 X 会话相关环境变量的最安全方法是从登录到 X 的用户进程的环境中获取它们。这是我用于完全相同目的的脚本的改编版(尽管 DBUS_SESSION_BUS_ADDRESS 不在 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"
Run Code Online (Sandbox Code Playgroud)

这会将消息发送给它找到的第一个 X 用户,尽管您可以添加一个循环将其发送给所有用户。

更新

似乎对 utmp 格式的更新会导致who在其第二列中打印显示而不是 tty。这实际上使事情变得更容易,以前它只在最后的评论中打印显示,我认为依靠原始答案是不安全的。如果是这种情况,请尝试以下操作:

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"
Run Code Online (Sandbox Code Playgroud)


小智 7

我在 Ubuntu 18.04 上使用 i3。我解决这个问题的方法是:

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


PJ *_*net 5

这条单线在 Manjaro 和 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.'
Run Code Online (Sandbox Code Playgroud)

如果没有非常丑陋的 DBUS_blah_blah,它根本无法工作。我也觉得journalctl -xb -u cronie很有帮助。FWIW,Cronie 使用 crond 并且应该向后兼容 Vixie cron。

我在这里找到了解决方案https://wiki.archlinux.org/index.php/Desktop_notifications

更新:2021 年仍然有效。我将这些提示添加到我的 /etc/crontab 文件中。

# After installing cronie:
# systemctl start cronie
# systemctl enable cronie

# After editing this file:
# chmod 600 /etc/crontab    
# crontab /etc/crontab
# Check that the changes are set:
# crontab -l
Run Code Online (Sandbox Code Playgroud)