命令未在 cron 中运行(systemctl 挂起)

命令未在 cron 中运行(systemctl 挂起)

我设置了这个 cronjob :

* * * * * /usr/bin/systemctl suspend

但它不起作用。但我可以在 shell 中运行它并且它可以工作。我不明白什么可能不起作用。

编辑 将错误输出重定向/tmp/error到:

Failed to issue method call: Access denied
Failed to issue method call: Access denied

我的问题是: cronjobs 是否作为特殊用户运行(cron例如),这将解释我的用户可以运行该命令,但不能运行cron其本身?

附加说明:

  • 这是一个最小的示例,用于显示我在脚本中遇到的问题(这比此处提供的单个命令更有意义)

  • systemctl是其一部分systemd。我认为重新启动、关闭、挂起正在与非 root 用户一起使用systemd。无论如何,它在我的系统上运行。

  • 最后,我使用 Arch Linux,并且/bin/usr/sbin/sbin都是到 的符号链接/usr/bin

答案1

我无法真正回答,但我想我可以为您指出正确的方向。我在 Arch Wiki 中找到了这个systemd

波尔基特对于电源管理来说是必要的。如果您位于本地 systemd-logind 用户会话中并且没有其他会话处于活动状态,则以下命令无需 root 权限即可运行。如果没有(例如,因为另一个用户登录到 tty),systemd 将自动询问您 root 密码。

[各种systemctl命令列表]

systemctl 挂起

这向我暗示了以下可能性:

  1. 您有另一个用户登录。也许您是通过 tty 登录的?

  2. cron使用 运行其命令/bin/sh默认情况下,在 Arch 上这是一个符号链接/bin/bash。这意味着cron启动一个非交互式 bash shell,然后检测到有另一个用户会话正在运行(您的),因此尽管以您的用户身份运行,但它无权运行systemctl

因此,如果您的问题是因为您已经登录cron而不允许运行systemctl,您也许可以通过玩来解决这个问题波尔基特但我没有那里的经验所以我无能为力。

答案2

一个简单的解决方法是使用 root 的 crontab 而不是您自己的。编辑它:

$ sudo crontab -e

代替:

$ crontab -e

答案3

有一个更简单的解决方案,无需 sudo,使用systemd-run:

重要的是您必须DBUS_SESSION_BUS_ADDRESS为相关用户设置/导出环境变量。只需创建一个名为或其他名称的脚本systemctl-suspend,其中包含以下几行:

#!/bin/bash
# This is a workaround script to be able to use 'systemctl suspend' in user-cron
PATH=/usr/bin
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/"$(id -u "$LOGNAME")"/bus
systemd-run --user systemctl suspend

并使其可执行,然后将该脚本文件复制到文件夹,例如/usr/local/bin.

最后,在用户的 crontab 中启动脚本,如下所示:

0 22 * * * /usr/local/bin/systemctl-suspend

在 Debian 10 (buster) 上测试。

答案4

引用自这里:

另一个答案是很棒的!但它需要root cron。

如果你想从非 sudo cron 休眠,有 2 个选项:

1. 使用波尔基特

创建一个包含以下内容的文件:

[Enable hibernate to be run via cron]
Identity=unix-user:*
Action=org.freedesktop.login1.hibernate;org.freedesktop.login1.hibernate-multiple-sessions
ResultAny=yes 

com.0.enable-hibernation-from-cron.pkla在目录中 命名/etc/polkit-1/localauthority/50-local.d/

已给出解释 这里

2. 使用维苏多

引用自 这里:

如果只允许用户使用 shutdown 命令,而没有其他 sudo 权限,则以 root 身份将以下内容添加到末尾 /etc/sudoers使用visudo命令。

user hostname =NOPASSWD: /usr/bin/systemctl poweroff,/usr/bin/systemctl halt,/usr/bin/systemctl reboot

替换user您的用户名和hostname计算机的主机名。
现在您的用户可以使用 关机sudo systemctl poweroff,然后使用 重新启动sudo systemctl reboot。希望关闭系统电源的用户也可以使用sudo systemctl halt
仅当您不想提示输入密码时才使用 NOPASSWD: 标记。

就我而言,确切的行是:

anmol ALL=NOPASSWD: /bin/systemctl hibernate

(请注意,您系统上的位置systemctl可能有所不同。)

之后,您可以编写sudo systemctl hibernatecron 来休眠。

注:直接修改/etc/sudoers坏的;而是在下面创建一个自定义 sudoers 文件/etc/sudoers.d/使用命令 - sudo visudo -f /etc/sudoers.d/custom

相关内容