I have a script run from a non-privileged users’ crontab that invokes some commands using sudo. Except it doesn’t. The script runs fine but the sudo’ed commands silently fail.
- The script runs perfectly from a shell as the user in question.
-
Sudo does not require a password. The user in question has
(root) NOPASSWD: ALLaccess granted in/etc/sudoers. -
Cron is running and executing the script. Adding a simple
date > /tmp/logproduces output at the right time. - It’s not a permissions problem. Again the script does get executed, just not the sudo’ed commands.
-
It’s not a path problem. Running
envfrom inside the script being run shows the correct$PATHvariable that includes the path to sudo. Running it using a full path doesn’t help. The command being executed is being given the full path name. -
Trying to capture the output of the sudo command including STDERR doesn’t show anything useful. Adding
sudo echo test 2>&1 > /tmp/logto the script produces a blank log. -
The sudo binary itself executes fine and recognizes that it has permissions even when run from cron inside the script. Adding
sudo -l > /tmp/logto the script produces the output:User ec2-user may run the following commands on this host:
(root) NOPASSWD: ALL
Examining the exit code of the command using $? shows it is returning an error (exit code: 1), but no error seems to be produced. A command as simple as /usr/bin/sudo /bin/echo test returns the same error code.
What else could be going on?
This is a recently created virtual machine running the latest Amazon Linux AMI. The crontab belongs to the user ec2-user and the sudoers file is the distribution default.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
sudo has some special options in its permissions file, one of which allows a restriction on its usage to shells that are are running inside a TTY, which cron is not.
Some distros including the Amazon Linux AMI have this enabled by default. The /etc/sudoers file will look something like this:
# Disable "ssh hostname sudo <cmd>", because it will show the password in clear. # You have to run "ssh -t hostname sudo <cmd>". # Defaults requiretty # # Refuse to run if unable to disable echo on the tty. This setting should also be # changed in order to be able to use sudo without a tty. See requiretty above. # Defaults !visiblepw
If you had captured output to STDERR at the level of the shell script rather than the sudo command itself, you would have seem a message something like this:
sorry, you must have a tty to run sudo
The solution is to allow sudo to execute in non TTY environments either by removing or commenting out these options:
#Defaults requiretty #Defaults !visiblepw
Method 2
A bit late, and probably no longer of interest to the OP, but for others who may be struggling with the use of sudo in a user crontab, here’s a potential solution:
Instead of using sudo in a user crontab, use the root crontab:
$ sudo crontab -e
In some systems – depending on how sudo is configured – using sudo in a user crontab will actually work (e.g. Raspberry Pi OS). However, using the root crontab is a more portable approach; it also eliminates the need to use sudo to run any command or script. So, if you used sudo mount 'blah, blah' in a user crontab, it becomes mount 'blah, blah' in the root crontab.
If you don’t know what the environment is for jobs run under cron, you can ask cron to tell you by adding this entry to the root crontab (sudo crontab -e):
0 12 * * * /usr/bin/printenv > /home/user_me/cronenvironment_sudo.txt 2>&1
Change user_me to an actual username on your system, and see the crontab guru for help with the schedule.
And finally, see this Q&A for how to change the environment in cron.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0