我在 Raspberry Pi 上运行这个简单的脚本来自动更新,这样我就可以忘掉它了。它还会保留一个日志,显示更新是否成功。脚本是 update.sh:
#!/bin/bash
echo "Update starts on: $(date)" >> /home/pi/update.log
if apt-get update && apt-get upgrade -y; then
echo "update successful $(date)" >> /home/pi/update.log
else
echo "Couldn't update $(date)" >> /home/pi/update.log
fi
我使用这个脚本添加到了根 crontab 中sudo crontab -e
,并将 cronjob 设置为每天早上 6 点运行
0 6 * * * /home/pi/update.sh
我知道它在某种程度上是有效的,因为sudo ./update.sh
在 shell 中运行会手动运行命令并在日志中留下“成功”条目。另一方面,当从 crontab 运行时,我总是得到“无法更新”条目。万一有问题,“update.sh”脚本是由“pi”用户创建的,我从未更改过权限,除了授予它执行权限。
我读了另一个关于同一问题的问题,那个人通过在sudo
命令前面加上一个来解决这个问题。他承认这很奇怪,因为它已经被 root 执行了,但他说它可以工作。我尝试添加sudo
并验证它现在确实有效。
sudo
有人知道为什么会发生这种情况吗?如果已经是 root 用户,为什么还需要?
答案1
Cron 从一个特殊的 shell 运行命令,该 shell 与用户或 root shell 是分开的。此 shell 无法访问与用户相同的 PATH 变量。因此,当将脚本作为 cron 作业运行时,有两个选项:
A. 指定脚本中每个命令的完整路径(即 aptitude 的完整路径 - cron 不知道在哪里查找“apt-get”)
B. 我使用的小技巧 - 编写 cron 作业行时,即使在 ROOT crontab 中,也要在脚本路径前附加 sudo。这将诱使 cron 从 root shell 而不是 cron shell 运行脚本,这将使其能够访问所有 root 的 PATH 变量。
答案2
这是因为 cron 以您的非特权用户身份运行,而apt-get
命令需要 root(又名管理员)提升权限才能运行。
root
另一种方法是在用户的 crontab下运行此命令:
sudo -i
<type user password>
crontab -e
第一个命令将您的整个 shell 提升为 root,并且还将 - 至关重要的是 - 让您访问 root 的环境,而不仅仅是以具有提升权限的用户身份执行单个命令。
第二条命令将编辑根 crontab,而不是您自己的。