我正在尝试运行一个简单的脚本,该脚本检查电池百分比并通过通知显示它(notify-send
)。
如果从终端手动运行,脚本将正确运行:~/path-to-script/my_script.sh
或sh ~/path-to-script/my_script.sh
甚至bash ~/path-to-my-script/my_script.sh
。
正确意味着显示通知。
但是,尝试运行它时cron
没有出现任何通知。如下所示crontab -e
:
*/1 * * * * /usr/bin/sh ~/path-to-my-script/my_script.sh
我还设置了一些环境crontab
变量sudo vim /etc/crontab
:
SHELL=/usr/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
这是来自的日志sudo service cron status
:
gen 28 17:35:01 my_user CRON[7863]: pam_unix(cron:session): session opened for user my_user(uid=1001) by (uid=0)
gen 28 17:35:01 my_user CRON[7864]: (my_user) CMD (/usr/bin/sh ~/path-to-my-script/my_script.sh)
gen 28 17:35:01 my_user CRON[7863]: (CRON) info (No MTA installed, discarding output)
gen 28 17:35:01 my_user CRON[7863]: pam_unix(cron:session): session closed for user my_user
我在 Ubuntu 22.04 上运行,使用 i3 作为窗口管理器。此问题可能是什么原因造成的?
是否需要更多信息,请询问。
答案1
现代而简洁的方法是使用用户的systemd 定时器。缺少 DBus 环境变量只是cron 过时的众多原因之一在现代 Ubuntu Linux 上。
- 粘贴此内容
~/.config/systemd/user/battery_notification.service
:
[Unit]
Description=Sends notification about battery status
[Service]
# %h means ~
ExecStart=%h/path-to-my-script/my_script.sh
Type=oneshot
- 粘贴此内容
~/.config/systemd/user/battery_notification.timer
:
[Unit]
Description=Show battery notification every minute
# If you want to limit it to a specific desktop environment,
# you can change this line.
# This mostly prevents unnecessary runs in SSH or after logging out,
# and is another advantage over cron.
# EDIT: Too bad i3 has a bug that breaks this: https://github.com/i3/i3/issues/5186
#Requisite=graphical-session.target
#PartOf=graphical-session.target
[Install]
#WantedBy=graphical-session.target
WantedBy=dbus.service
[Timer]
AccuracySec=1us
# Initial delay
OnActiveSec=1s
# Period
OnUnitActiveSec=1m
- 运行以下命令:
systemctl --user daemon-reload
systemctl --user enable battery_notification.timer
systemctl --user start battery_notification.timer # Or reboot
您将看到 DBus 环境变量将一起很多别的缺少的环境变量已正确设置。该程序现在也是您的某个用户进程的子进程,即systemd --user
不是 cron,因此它位于正确的 cgroup 和其他命名空间中。
另一个优点是,当您注销或未登录指定的图形环境时,它会停止。有用的命令可能是systemctl --user list-timers
检查剩余时间或systemctl --user disable battery_notification.timer && systemctl --user stop battery_notification.timer
停止它。
答案2
正如我在评论中所述,解决方案是:env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus
在命令前面添加crontab -e
以下内容:
*/1 * * * * env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus /usr/bin/sh ~/path-to-my-script/my_script.sh