I'm running this simple script on my Raspberry Pi to auto update so I can forget about it. It also keeps a log that says whether the update was successful. The script is 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

I added this script to the root crontab by using sudo crontab -e and the cronjob is set to run every day at 6AM

0 6 * * * /home/pi/update.sh

I know that it works to some extent because running sudo ./update.sh in the shell manually runs the commands and leaves a "successful" entry in the log. On the other hand, when ran from the crontab, I always get the "couldn't update" entry. In case it matters, the "update.sh" script was created by the "pi" user and I never changed the permissions, except giving it execution permissions.

I read another question about the same problem and the guy solved it by putting a sudo in front of the command. He admits it's weird because it's already being executed by root, but says it works. I tried adding the sudo and verified it actually works now.

Does anyone know why this happens? Why does it need the sudo if it's already root?

  • 1
    I read that post and it gave a practical solution, but I don't think it gave an actual answer, not that I understood anyway. I rephrased the question to reflect that. – freejuices Jan 30 '15 at 18:27
  • 2
    The environment for sudo and pure root are not necessarily the same. try typing env as root and then sudo env and compare the results. – Nifle Jan 30 '15 at 18:31
  • 1
    It's like Windows UAC logged in as Administrator. Although you're logged in as the admin you are still just a normal user. To run a system function you have to "ask" for an admin token that gives you the ability to perform the task. This is the same for Linux (where, I believe, the idea originated) as it prevents the user accidentally doing something daft that could potentially ruin a system. – Kinnectus Jan 30 '15 at 18:57
  • 1
    Does the failing apt-get command report any errors? Since you're not redirecting its output, it will be sent as mail to root. – Barmar Jan 30 '15 at 19:10

Cron runs commands from a special shell, separate from the user or root shells. This shell does not have access to the same PATH variables as users. Therefore, when running a script as a cron job there are two options:

A. Specify the full path for every command in the script (I.e. full path to aptitude- cron doesn't know where to look to find "apt-get")

B. Little trick I use- when writing the cron job line, even in the ROOT crontab, append sudo before the script path. This will trick cron into running the script from a root shell instead of the cron shell, which will give it access to all root's PATH variables.

This is because the cron is running as your unprivileged user, and the apt-get commands require root (aka administration) elevation privileges to run.

An alternative is to run this command under the root user's crontab:

sudo -i
<type user password>
crontab -e

The first command elevates your entire shell to root and will also - crucially - give you access to root's environment, rather than just a single command as your user with elevated privileges.

The second command will edit the root crontab, not your own.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.