How to use cron on Ubuntu to automate any task

Key Takeaways

- Cron jobs require five time fields (minute, hour, day, month, weekday) to define any schedule
- Always use absolute paths in cron jobs because cron runs with a minimal environment
- Monitor cron jobs with logging or external tools since they fail silently by default
Cron is the standard task scheduler on Ubuntu and other Unix-like systems. It runs commands at intervals you define, from every minute to once a year, without requiring you to remember or intervene. If you manage servers, automate backups, or rotate logs, cron is probably already doing the work. This guide covers installation, syntax, common pitfalls, and when systemd timers might serve you better.
What is cron and why does it matter?
Cron is a daemon that wakes up every minute, checks scheduled jobs, and runs any that match the current time. The name comes from "chronos," the Greek word for time. System administrators have relied on it since the 1970s, and it remains the default scheduler in most Linux distributions.
The power is in the simplicity. You define when a command runs, cron handles execution, and you get on with other work. Database backups at 2 AM, disk usage reports every Monday, certificate renewal checks daily. Tasks that humans forget, cron remembers.
“Save your brain for higher-level thinking. Use your organizer for storing information. Don't trust your brain... Automate what you can and document what you can't.”
— Tom Limoncelli, Author of 'Time Management for System Administrators'
How to install cron on Ubuntu
Ubuntu ships with cron pre-installed. Verify it's running with this command:
systemctl status cronIf cron isn't installed (rare on Ubuntu, more common on minimal container images), install it:
sudo apt update && sudo apt install cronEnable it to start on boot:
sudo systemctl enable cronUnderstanding cron syntax
Every cron job has five time fields followed by the command to run. The fields represent minute, hour, day of month, month, and day of week. An asterisk means "every."
The format looks like this:
Code sample: * /path/to/command
│ │ │ │ │
│ │ │ │ └── Day of week (0-7, Sunday is 0 or 7)
│ │ │ └──── Month (1-12)
│ │ └────── Day of month (1-31)
│ └──────── Hour (0-23)
└────────── Minute (0-59)
Some practical examples:
- 0 5 * — Run at 5:00 AM every day
- /15 * — Run every 15 minutes
- 0 0 0 — Run at midnight every Sunday
- 30 4 1 — Run at 4:30 AM on the first of each month
- 0 9-17 1-5 — Run every hour from 9 AM to 5 PM, Monday through Friday
How to edit your crontab
Each user has their own crontab file. Open yours with:
Code sample: crontab -e
The first time you run this, Ubuntu asks which editor to use. Pick nano if you're unsure. Add your job on a new line, save, and exit. The cron daemon automatically picks up changes.
View your current crontab without editing:
Code sample: crontab -l
Remove your crontab entirely (careful with this one):
Code sample: crontab -r
System administrators can also edit another user's crontab:
Code sample: sudo crontab -u username -e
Why cron jobs fail silently
The most common cron frustration: a job works when you run it manually but fails when cron runs it. The culprit is almost always the environment. Cron runs with a minimal PATH, usually just /usr/bin and /bin. If your script calls a program installed elsewhere, cron can't find it.
Fix this by using absolute paths everywhere. Instead of:
Code sample: python backup.py
Write:
Code sample: /usr/bin/python3 /home/user/scripts/backup.py
You can also set environment variables at the top of your crontab:
Code sample: PATH=/usr/local/bin:/usr/bin:/bin
HOME=/home/user
0 5 * /home/user/scripts/backup.sh
How to debug cron jobs on Ubuntu
Cron logs to syslog by default. Check recent cron activity with:
Code sample: grep CRON /var/log/syslog
This shows when cron started each job but not the job's output. To capture output, redirect stdout and stderr in the cron entry itself:
Code sample: 0 5 * /home/user/scripts/backup.sh >> /var/log/backup.log 2>&1
For critical jobs, consider a monitoring service. Tools like Healthchecks.io or Cronitor expect a ping from your job. If the ping doesn't arrive on schedule, they alert you. This catches the "silent failures" that make cron debugging painful.
Cron vs systemd timers: which should you use?
Modern Ubuntu systems include systemd timers as an alternative to cron. Timers integrate with systemd's logging and service management. They can also handle dependencies and run missed jobs after a reboot.
| Feature | Cron | Systemd Timers |
|---|---|---|
| Setup complexity | One line per job | Two unit files per job |
| Logging | Manual redirection | journalctl integration |
| Missed jobs after reboot | Not run | Persistent option available |
| Dependency handling | None | Full systemd dependency graph |
| Portability | Works on any Unix | Linux with systemd only |
Use cron when you need quick, portable scheduling. Use systemd timers when you need better logging, dependency management, or guaranteed execution after downtime.
Practical cron job examples
Here are production-ready examples for common tasks:
Daily database backup at 3 AM:
Code sample: 0 3 * /usr/bin/mysqldump -u root mydb > /backups/mydb-$(date +\%Y\%m\%d).sql
Clear tmp files older than 7 days, every Sunday:
Code sample: 0 0 0 /usr/bin/find /tmp -type f -mtime +7 -delete
Renew Let's Encrypt certificates twice daily (recommended by Certbot):
Code sample: 0 0,12 * /usr/bin/certbot renew --quiet
Send disk usage report every Monday at 9 AM:
Code sample: 0 9 1 /usr/bin/df -h | /usr/bin/mail -s "Disk Report" admin@example.com
Common cron mistakes to avoid
- Using relative paths. Always use absolute paths for commands and files.
- Forgetting to escape percent signs. In crontab, % is a newline. Use \% for literal percent.
- Not testing manually first. Run your exact command in a minimal shell before adding it to cron.
- Ignoring output. Redirect output to a log file or /dev/null, otherwise cron tries to email it.
- Scheduling overlapping jobs. If a job takes 10 minutes, don't run it every 5 minutes.
Another practical automation case study
Frequently Asked Questions
How do I run a cron job every 5 minutes?
Use /5 in the minute field: /5 /path/to/command. The */5 syntax means 'every 5th minute.'
Why isn't my cron job running?
Check three things: the cron daemon is running (systemctl status cron), your syntax is correct (no typos in the schedule), and your command uses absolute paths. Then check /var/log/syslog for errors.
How do I see all cron jobs on the system?
For your user, run crontab -l. For other users, sudo crontab -u username -l. System-wide jobs live in /etc/crontab and the /etc/cron.* directories.
Can I run a cron job as root?
Yes. Use sudo crontab -e to edit root's crontab, or add jobs to /etc/crontab with the username field.
What's the difference between user crontab and /etc/crontab?
User crontabs (edited with crontab -e) don't include a username field. /etc/crontab and /etc/cron.d files require a username between the schedule and command.
Logicity's Take
Cron's staying power comes from doing one thing well. Fifty years later, the five-field syntax remains the fastest way to schedule a job. But that simplicity hides sharp edges: silent failures, environment mismatches, and logs scattered across syslog. For anything beyond simple scripts, pair cron with external monitoring. A $0 tool like Healthchecks.io can save hours of debugging. And if you're building new infrastructure, consider systemd timers for their logging alone.
Need Help Implementing This?
Setting up reliable cron jobs for production workloads requires careful planning. Contact the Logicity team for guidance on automation infrastructure, monitoring solutions, and migration to systemd timers if that fits your stack better.
Huma Shazia
Senior AI & Tech Writer
Related Articles
Browse all
Google Workspace API Updates March 2026: New Calendar API, Chat Authentication, and Maps Changes
Google just dropped Episode 29 of their Workspace Developer News, and there's a lot to unpack. From a brand new secondary calendar lifecycle API to deprecation warnings for Apps Script authentication, here's everything developers need to know about the March 2026 platform updates.

Zig for Legacy C Code: How to Modernize Infrastructure Without a Risky Full Rewrite
A new blueprint from Zeba Academy shows developers how to surgically replace fragile C components with Zig modules. Instead of risky full rewrites, this approach lets you swap out problematic code piece by piece while keeping your battle-tested infrastructure intact.

Claude Skills vs Commands: When to Use Each for AI-Powered Coding Workflows
Claude's Skills and Commands look similar on the surface since both use markdown files, but they work completely differently. Skills run automatically based on context while Commands need explicit /invocation. Here's how to pick the right one for your coding workflow.

DualClip macOS Clipboard Manager: The Only Tool That Uses Dedicated Slots Instead of History
DualClip v1.2.6 just dropped with a major stability fix and Homebrew support. After analyzing 57 clipboard managers, the developer found every single one uses history. DualClip takes a radically different approach with three fixed slots and zero disk storage.

