在cron中使用notify-send


32

我正在将Arch Linux与KDE / Awesome WM一起使用。我正在努力 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 ~]$ 

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

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

但是要注意的是,该变量不是该帖子的永久变量,因此我将尝试在那里建议的命名管道解决方案。

[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

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


据我所知,这应该可以工作。为什么不将a添加&>>/tmp/crontest到通知发送行,看看是否notify-send给出任何错误消息。
Graeme 2014年

出于好奇,您尝试了我的解决方案吗?它看起来更简单,并且可以在我的Debian上完美运行。我问的只是想知道它是否是Debian专用的
terdon

@terdon我尝试了您的解决方案(只是一个快速测试),它似乎可以在我的Debian系统上运行。我想知道它是否普遍适用,因为它确实更简单。
Marco Marco

@Marco我正在LMDE(基本上是Debian测试)上,并使用Cinnamon作为DE。无法告诉您它是否还能解决这些问题。
terdon

@Marco&Terdon:Ubuntu的人可以这样做:ubuntuforums.org/showthread.php?t=1727148
刚刚

Answers:


29

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

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

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

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

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


1
很高兴看到我快要解决了。谢谢Marco,这很干净!
justsomeone 2014年

太好了,我重新使用了您的答案,并在此处添加了一些更详细的说明:askubuntu.com/a/537721/34298
rubo77


@Gilles如何像聊天中提到的
rubo77

我已经尝试了许多其他答案,但不包括ubuntu 15.10上的DBUS,并且没有任何效果。那是简单的并且可以完美地工作。
bastian 2015年

16

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

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

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

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


感谢您的宝贵时间。这似乎是一个简单的解决方案。不幸的是,这对我不起作用,
某人2014年

@justsomeone呵呵,好的,那可能取决于桌面环境。
terdon

我认为这与发行版或桌面环境有关。对于Ubuntu用户,从我在在线论坛上看到的内容来看,直接解决方案似乎可以正常工作。
justsomeone 2014年

@justsomeone我在使用Cinnamon作为DE的Debian(LMDE)上。可能与X的启动方式或DE所使用的通知系统dunno有关。
terdon

确认它可以在Ubuntu 14.04 / 14.10上运行。使用GNOME和Unity。
Jordon Bedwell 2014年

8

获取与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"

尽管您可以添加一个循环将其发送给所有用户,但是这会将消息发送给它找到的第一个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"

这对我在Trusty上不起作用,因为该who_line命令中未打印任何tty 。输出看起来像me :0 2015-09-23 10:40 ? 17234
blujay 2015年

1
@blujay,已更新。
Graeme

谢谢,那行得通。但是,正如我在一个单独的答案中发布的那样,还有一个更简单的解决方案。
blujay

@blujay是的,这是一个可移植的答案。虽然不能确定是否确实可行,但是在大多数情况下仍然可以使用。
Graeme

2

这位单身人士与克罗尼(Cronie)在曼贾罗(Manjaro)为我工作:

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

没有非常丑陋的DBUS_blah_blah,它根本无法工作。我也发现journalctl -xb -u cronie有帮助。我还不熟悉Cronie,但是创建了我的“ crontab”,/etc/cron.d/mycronjobs并且不确定是否需要该文件名,或者它是否仅读取cron.d目录中的所有内容。

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


2

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

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


1

这足以在Ubuntu Trusty的cronjob中使通知发送对我有用:

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

它只是DISPLAY为运行cronjob的用户导出。它对我有效而无需设置XAUTHORITYDBUS_SESSION_BUS_ADDRESS


1
同样适用于Ubuntu 16.04。我实际上是cron启动一个Perl脚本,而system()是bash脚本,它启动另一个Perl脚本,该脚本执行一个system(“ notify-send ...”)。将导出命令添加到bash脚本中修改了该脚本的环境,然后该环境继承了最后一个Perl脚本并可供系统使用(“ notify-send ...”)。很好发现blujay!
蒂姆(Tim)

1

对于那些愿意安装Python软件包的Linux用户,我刚刚发布了一个notify-send-headless程序,对我来说效果很好。它搜索/proc所需的用户名和环境变量,然后notify-send使用这些变量运行(sudo如有必要,它将用于切换到所需的用户)。


1

您还可以编写一个脚本:

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

然后运行sudo。但是,由于crontab -e与创建它的用户一起运行所有命令,因此在不使用的情况下调用以下命令就足够了sudo

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

至少对我有用。一切似乎都取决于环境配置。


0

我在cron中使用此脚本将MPD发布到每小时播放一次的Twitter上

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

使用notify-send的类似脚本

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

您可能会遇到问题,因为KDE使用其自己的notify-deamon IIRC。


0

物有所值....

我必须在Debian Jessie上使用以下所有功能,才能使其正常工作...

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

遗漏其中任何一个都会导致它停止工作。


最后一行不会像这里写的那样做任何事情,因为不会有任何字面的文件 *-0session-bus目录的文件。你可能是故意的source "$HOME"/.dbus/session-bus/*-0
roaima

0

使用sudo:

sudo -u $currentxuser notify-send $message

小费 :

我们可以通过此命令获取当前的x用户

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

此外...

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

很高兴知道 :

在root下运行的Cron无法访问x,因此不会显示所有gui命令,一种简单的解决方案是使用此命令将root添加到当前x用户的授权x用户

从x用户外壳

xhost local:root

要么

sudo -u $currentxuser xhost local:root

-1

这是比Graeme提供的脚本更简单的脚本。他的剧本对我不起作用,$who_line总是空虚的。我的脚本并没有浪费太多时间来查找进程。相反,它只是尝试所有操作并选择找到的最后一个有用值。我正在运行xubuntu 14.04,并且有一些正在运行的lxc容器可能会混淆这种脚本。

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"

在Trusty上,这对我不起作用,因为Xorg进程的环境没有DBUS_SESSION_BUS_ADDRESS。我可以从外壳程序中获得它,但不能从Xorg进程中获得它。
blujay 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.