Notify-send在crontab中不起作用

我制作了一个脚本,当我正在阅读漫画的新章节时,它应该通知我。 我使用命令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命令查看命令“活动”的位置

事情似乎在13.04有所不同,至少在Gnome Shell。

首先,这是从用户zzyxy (而不是root的)cron作业运行时的env打印:

 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工作,根据DahitiF对ubuntuforums.org 的评论 ,似乎有必要设置DBUS_SESSION_BUS_ADDRESS环境变量。 只需在您的实际工作描述中添加以下内容:

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

似乎没有必要设置DISPLAY

当cron启动时,命令notify-send不会在屏幕上显示消息。 只需在脚本顶部添加目标显示,例如:

 export DISPLAY=:0 

至少对于Ubuntu 14.04, klrmr上面的回答是正确的答案。 似乎没有必要为$ PATH设置DISPLAY或清晰表达notify-send或其他任何通常的路径。

下面是我用来在笔记本电脑的电池状态变得太低时关闭虚拟机的cron脚本。 klrmr上面的响应中的行设置DBUS_SESSION_BUS_ADDRESS是最终使警告正常工作的修改。

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

在我使用ubuntu 16.04的情况下,需要任何显式路径,我只是添加解决问题

DISPLAY =:0

在调用notify-send之前,在crontab的第一行。

第一个罪魁祸首是你的crontab文件,你还需要提到脚本必须用来执行的用户名,最好把它保存为root

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

然后你应该在脚本中使用GUI用户的user_name并将其作为notify-send的前缀添加“sudo或su”,以拥有GUI的用户身份执行命令

例子:

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

要么

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

其中gnome_user_name是启动GUI会话的用户的用户名,是您登录的用户,如果您想使其成为动态选择,您可以从

 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" 

二进制检索dbus地址的方式似乎最近发生了变化。 在带有“notify-send 0.7.6”的Ubuntu 15.04(Vivid Vervet)上,需要以下两个变量:

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

‘krlmlr’的语句评估正常并设置正确的地址,但对话框不会从cron作业弹出。

如果crontab中的脚本以root用户身份运行,则上述答案可能无效。 试试这个function,16.04对我来说很好用:

 notify_all() { local title=$1 local msg=$2 who | awk '{print $1, $NF}' | tr -d "()" | while read ud; 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 )

最好依赖于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上工作,必须添加一个源来获得用户正常的env变种。 我的显示是:1出于某种原因。 使用gnome-session首先获得DBUS_SESSION_BUS_ADDRESS查找的pid。

 # 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)" 

我刚刚在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" 

诀窍是要意识到’肉桂会话’太长了,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'