cron 无法运行 .sh 脚本 - 22.04

cron 无法运行 .sh 脚本 - 22.04

我正在尝试运行一个简单的脚本,该脚本检查电池百分比并通过通知显示它(notify-send)。
如果从终端手动运行,脚本将正确运行:~/path-to-script/my_script.shsh ~/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 上。

  1. 粘贴此内容~/.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
  1. 粘贴此内容~/.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
  1. 运行以下命令:
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

相关内容