Understanding Ubuntu’s cron.daily: Why Jobs Fail and How to Fix Correctly


2 views

In Ubuntu systems, the /etc/cron.daily/ directory is part of the standard cron setup. However, there's a crucial detail many admins miss: scripts here don't run via traditional cron but through anacron, which has different scheduling logic.

# Check if anacron is installed (Ubuntu server minimal might not have it)
dpkg -l | grep anacron

# Verify cron.daily execution in syslog (note the different log pattern)
grep -i cron.daily /var/log/syslog | tail -n 5

Common failure patterns include:

  • Missing execute permissions: chmod +x /etc/cron.daily/your_script
  • Script dependencies not available in restricted cron environment
  • Output not being captured (scripts should handle logging explicitly)
#!/bin/bash
# Proper cron.daily script template

LOGFILE=/var/log/custom_daily.log
{
    echo "$(date) - Starting daily job"
    
    # Main logic here
    /usr/bin/your_command --some-flag
    
    echo "$(date) - Job completed"
} >> "$LOGFILE" 2>&1

For modern Ubuntu systems (18.04+), consider using systemd timers instead:

# Example systemd timer unit
[Unit]
Description=Daily maintenance job

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
  1. Verify script has execute permission (+x)
  2. Test script runs manually: sudo /etc/cron.daily/your_script
  3. Check /var/mail/root for error messages
  4. Confirm anacron is active: systemctl status anacron

In Ubuntu systems, the /etc/cron.daily/ directory is part of the anacron system designed for systems that aren't running 24/7. Contrary to popular assumption, scripts placed here don't execute through the standard cron daemon but are instead managed by run-parts via /etc/crontab:

# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd /amp;& run-parts --report /etc/cron.monthly )

Several factors could prevent your script from executing:

  • File permissions: Scripts must be executable (chmod +x /etc/cron.daily/your_script)
  • Naming conventions: Avoid special characters and extensions (.sh typically not needed)
  • Shebang line: Missing interpreter directive (e.g., #!/bin/bash)
  • Path issues: Absolute paths should be used for commands

Create a test script with explicit error output:

#!/bin/bash
# /etc/cron.daily/testjob
echo "$(date) - Test job started" >> /var/log/cron_test.log
/usr/bin/your_command >> /var/log/cron_test.log 2>&1
echo "$(date) - Exit status: $?" >> /var/log/cron_test.log

Then force execution to test:

sudo run-parts --verbose /etc/cron.daily

For more predictable scheduling, consider using root's crontab:

sudo crontab -e
# Add this line for daily execution at 2:30 AM
30 2 * * * /path/to/your/script.sh

Modern Ubuntu systems can use systemd timers for better logging:

# /etc/systemd/system/myjob.timer
[Unit]
Description=Run myjob daily

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

# /etc/systemd/system/myjob.service
[Unit]
Description=My custom job

[Service]
Type=oneshot
ExecStart=/path/to/your/script.sh

Enable with:

sudo systemctl enable --now myjob.timer