Cron Sudo – Why Cron Fails to Run Sudo Commands in Scripts

cronsudo

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: ALL access granted in /etc/sudoers.

  • Cron is running and executing the script. Adding a simple date > /tmp/log produces 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 env from inside the script being run shows the correct $PATH variable 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/log to 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/log to 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.

Best Answer

Sudo has some special options in it's permissions file, one of which allows a restriction on it's 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
Related Question