LFCS 65 🐧 Traditional Cron Jobs
Cron is the oldest task scheduler still in daily use on Linux systems, and the LFCS exam tests it alongside systemd timers as a distinct scheduling mechanism. The exam objective is explicit: “Schedule tasks to run at a set date and time” and “Verify completion of scheduled jobs” . Cron’s model is simpler than systemd timers—a single daemon reads per-user and system-wide crontab files once per minute and executes any job whose five time fields match the current time. There is no dependency graph, no resource isolation, and no missed-run recovery unless anacron is involved. What cron provides is ubiquity: every Linux distribution ships it, every administrator recognizes it, and it works identically on systems that predate systemd.
The exam tests two crontab formats that differ by a single field. A user crontab, edited with crontab -e, has five time fields followed by the command, and all commands run as the user who owns the crontab . The system crontab at /etc/crontab, and files in /etc/cron.d/, have five time fields followed by a username field and then the command, allowing jobs to run as any user . The LFCS mock exam discussions show that confusing these two formats is a common failure point: a task that asks for a job to run as a specific user in the system crontab requires the username field, not a su command in a user crontab .
This chapter covers the five time fields and their ranges, the special characters (*, ,, -, /), the user versus system crontab distinction, the crontab command options, environment configuration, and the verification steps that confirm a job actually ran. It assumes familiarity with basic shell commands and file editing.
Key point: A user crontab has five time fields plus the command. A system crontab has five time fields plus a username plus the command. The username field is the difference, and it is what allows a system crontab entry to run a job as a non-root user without su.
Why traditional cron is still tested
Cron predates systemd and remains universally available. Every LFCS exam environment includes cron, and the exam objectives explicitly list scheduled tasks as an operational competency . systemd timers are the modern alternative, but cron is not deprecated—it is the baseline that every administrator is expected to know, and many production systems still use it for simple recurring jobs.
The five-field syntax is compact and unforgiving. A cron entry has exactly five time fields before the command, and each field has a fixed range: minute 0–59, hour 0–23, day of month 1–31, month 1–12, day of week 0–7 (0 and 7 both mean Sunday) . A blank field breaks the entry silently; cron does not validate the line and report an error. The job simply never runs, and the only diagnostic is the system log.
The user/system crontab distinction is an exam trap. A user crontab runs commands as the user who owns it. There is no username field. A system crontab at /etc/crontab has a username field after the time fields, and the command runs as that user . The LFCS mock exam forum thread documents a candidate who added a system crontab entry with a username field but used the wrong command structure, and the auto-grader expected a different approach . The lesson is that the format matters, and the username field is not optional in the system crontab.
Environment variables are minimal. Cron runs jobs with a minimal environment. PATH is typically /usr/bin:/bin, and the shell is /bin/sh unless overridden. A script that works interactively may fail in cron because it relies on a PATH entry or an environment variable that is absent. The fix is to set PATH and other variables at the top of the crontab, or to use absolute paths for every command .
The trade-off. Cron is simpler than systemd timers, but it lacks Persistent= for missed runs, dependency ordering, and resource limits. anacron provides missed-run recovery for workstations, but it is not a drop-in replacement for cron on servers . The exam tests cron because it is the baseline; systemd timers are tested separately because they are the modern alternative.
a. The five time fields and special characters
Every cron entry begins with five fields separated by spaces. The fields are minute, hour, day of month, month, and day of week. Each field accepts a number, a range, a list, or an asterisk.
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of week (0 - 7, 0 or 7 is Sunday)
# │ │ │ │ │
# * * * * * command
The special characters modify the field values. An asterisk (*) matches every value. A comma (,) separates a list: 1,15 in the day-of-month field runs on the 1st and 15th. A hyphen (-) defines a range: 9-17 in the hour field runs every hour from 9 AM through 5 PM. A slash (/) defines a step: */10 in the minute field runs every 10 minutes .
# Run at 4:00 AM on the 1st and 15th of every month.
0 4 1,15 * * /usr/local/bin/report.sh
# Run every 15 minutes during business hours on weekdays.
*/15 9-17 * * 1-5 /usr/local/bin/check.sh
# Run at 3:00 AM every Sunday (0 and 7 both mean Sunday).
0 3 * * 0 /usr/local/bin/cleanup.sh
The day-of-week field accepts 0 or 7 for Sunday. Some implementations also accept names like mon or sun, but the exam-safe approach is numeric values or the three-letter abbreviations if the system supports them . The month field accepts 1–12 or jan–dec.
b. User crontab versus system crontab
The user crontab is edited with crontab -e. It has five time fields followed by the command. The command runs as the user who owns the crontab. The crontab -l command lists the current user’s crontab, and crontab -r removes it .
# Edit the current user's crontab.
crontab -e
# List the current user's crontab.
crontab -l
# Remove the current user's crontab.
crontab -r
# Edit another user's crontab (requires root).
sudo crontab -u mary -e
The system crontab at /etc/crontab has a different format. It includes a username field after the time fields, before the command. The command runs as that user .
# /etc/crontab format: minute hour day month weekday user command
0 4 15 * * mary find /home/mary/ -type d -empty -delete
The system crontab is edited directly with a text editor, not with crontab -e. The /etc/cron.d/ directory contains additional system crontab files with the same format. The /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, and /etc/cron.monthly/ directories contain scripts that are run by run-parts on the corresponding schedule .
The LFCS mock exam forum thread highlights the confusion: a task asked to “add a cron job to the system-wide cron table” to run as a user named Mary. The candidate added an entry to /etc/crontab with the username field, which is technically correct for the system crontab format. The auto-grader expected a root user crontab entry using su - mary -c 'command'. The forum discussion concludes that the question phrasing was ambiguous, but the system crontab format with the username field is the technically accurate approach for running as a specific user .
c. Environment, output redirection, and verification
Cron runs jobs with a minimal environment. The default PATH is typically /usr/bin:/bin, which may not include the directory where a script or its dependencies live. The fix is to set environment variables at the top of the crontab .
# Set the shell and PATH for all jobs in this crontab.
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
# Redirect output to a log file for debugging.
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
# Discard all output (cron emails it by default if MAILTO is set).
0 3 * * * /usr/local/bin/cleanup.sh > /dev/null 2>&1
The MAILTO variable controls where cron sends job output. If MAILTO is set to a valid email address and a mail transfer agent is configured, cron emails the output. If MAILTO is empty (MAILTO=""), no email is sent. Redirecting output to a log file is the exam-safe approach because it does not depend on mail configuration .
Verification is a two-step process. crontab -l confirms the job is installed. The system log (/var/log/syslog or /var/log/cron) confirms it ran. The log entry includes the timestamp, the user, and the command . If the job produces output, the redirected log file shows it.
# Verify the job is installed.
crontab -l
# Check the system log for execution.
grep CRON /var/log/syslog
# Check the job's output log.
tail -n 20 /var/log/backup.log
Complete Example Session
# ============================================
# PART 1: THE FIVE TIME FIELDS
# ============================================
# minute hour day-of-month month day-of-week
# 0 3 * * * → daily at 3:00 AM
# 30 8 15 6 * → June 15 at 8:30 AM
# */15 9-17 * * 1-5 → every 15 min, weekdays, 9-5
# ============================================
# PART 2: SPECIAL CHARACTERS
# ============================================
# * = every value
# , = list (1,15 = 1st and 15th)
# - = range (9-17 = 9 through 17)
# / = step (*/10 = every 10)
# ============================================
# PART 3: USER CRONTAB (FIVE FIELDS)
# ============================================
# Edit the current user's crontab.
crontab -e
# Add a job (no username field).
# 0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
# List it.
crontab -l
# ============================================
# PART 4: SYSTEM CRONTAB (SIX FIELDS)
# ============================================
# /etc/crontab has a username field after time fields.
# 0 4 15 * * mary /usr/local/bin/mary-task.sh
#
# Edit with a text editor, not crontab -e.
sudo vim /etc/crontab
# ============================================
# PART 5: CRON.D DIRECTORY
# ============================================
# Additional system crontabs go in /etc/cron.d/.
# Same six-field format.
# sudo tee /etc/cron.d/myjob <<'EOF'
# 0 2 * * * root /usr/local/bin/root-job.sh
# EOF
# ============================================
# PART 6: ENVIRONMENT VARIABLES
# ============================================
# Set at the top of the crontab.
# SHELL=/bin/bash
# PATH=/usr/local/bin:/usr/bin:/bin
# MAILTO=admin@example.com
# ============================================
# PART 7: OUTPUT REDIRECTION
# ============================================
# Log stdout and stderr.
# 0 2 * * * /path/script.sh >> /var/log/script.log 2>&1
#
# Discard output.
# 0 2 * * * /path/script.sh > /dev/null 2>&1
# ============================================
# PART 8: LIST AND REMOVE
# ============================================
crontab -l # list current user's jobs
crontab -r # remove all current user's jobs
sudo crontab -u mary -l # list mary's jobs
# ============================================
# PART 9: VERIFY EXECUTION
# ============================================
# Check system log.
grep CRON /var/log/syslog
# Or on RHEL-based systems:
grep CROND /var/log/cron
# Check the job's own log.
tail -f /var/log/backup.log
# ============================================
# PART 10: THE EXAM CHECKLIST
# ============================================
# 1. User crontab: five fields + command (no username).
# 2. System crontab: five fields + username + command.
# 3. Use absolute paths for commands and scripts.
# 4. Redirect output to a log for debugging.
# 5. Verify with crontab -l and the system log.
# 6. The grader checks the crontab file, not a reboot.
Quick Reference
Time Field Ranges
| Field | Range | Notes |
|---|---|---|
| Minute | 0–59 | |
| Hour | 0–23 | 24-hour clock |
| Day of month | 1–31 | |
| Month | 1–12 | Names allowed (jan–dec) |
| Day of week | 0–7 | 0 and 7 = Sunday |
Special Characters
| Character | Meaning | Example |
|---|---|---|
* | Every value | * * * * * |
, | List | 1,15 |
- | Range | 9-17 |
/ | Step | */10 |
Crontab Formats
| Type | Fields | Example |
|---|---|---|
| User | 5 + command | 0 3 * * * /path/script.sh |
| System | 5 + user + command | 0 3 * * * root /path/script.sh |
Crontab Commands
| Command | Purpose |
|---|---|
crontab -e | Edit current user’s crontab |
crontab -l | List current user’s crontab |
crontab -r | Remove current user’s crontab |
crontab -u user -e | Edit another user’s crontab (root) |
Verification
| Check | Command |
|---|---|
| Job installed | crontab -l |
| System log | grep CRON /var/log/syslog |
| Job output | tail /var/log/job.log |
Best Practices
✅ Do This:
# Use absolute paths for commands and scripts. // ✅
0 3 * * * /usr/local/bin/backup.sh
# Set PATH at the top of the crontab. // ✅
PATH=/usr/local/bin:/usr/bin:/bin
# Redirect output to a log for debugging. // ✅
0 3 * * * /path/script.sh >> /var/log/job.log 2>&1
# Use the username field in system crontabs. // ✅
0 4 15 * * mary /path/mary-task.sh
❌ Don’t Do This:
# Use relative paths in cron jobs. // ❌
0 3 * * * backup.sh # Not found in cron's minimal PATH.
# Add a username field to a user crontab. // ❌
0 3 * * * mary /path/script.sh # Cron tries to run "mary".
# Assume cron inherits your interactive environment. // ❌
# Set PATH and other variables explicitly.
# Leave output unredirected without MAILTO. // ❌
# Output is lost or sent to local mail spool.
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Job never runs | Relative path not in cron’s PATH | Absolute paths or set PATH |
| User crontab syntax error | Username field added | Remove username from user crontab |
| System crontab job runs as root | Username field omitted | Add username after time fields |
| Output lost | No redirection and no MTA | Redirect to log file |
| Job fails silently | Minimal environment | Set SHELL and PATH |
Real-World Examples
1. Daily Backup at 3 AM
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
2. Weekdays at 9 AM
0 9 * * 1-5 /usr/local/bin/report.sh
3. Every 15 Minutes
*/15 * * * * /usr/local/bin/check.sh
4. First of Month
0 0 1 * * /usr/local/bin/monthly.sh
5. System Crontab with User
0 4 15 * * mary /home/mary/cleanup.sh
6. Cron.d File
sudo tee /etc/cron.d/myjob <<'EOF'
0 2 * * * root /usr/local/bin/root-job.sh
EOF
7. Set PATH
PATH=/usr/local/bin:/usr/bin:/bin
8. Redirect Output
0 2 * * * /path/script.sh >> /var/log/script.log 2>&1
9. List User Crontab
crontab -l
10. Verify Execution
grep CRON /var/log/syslog
Visual
User vs System Crontab
┌──────────────────────────────────────────────┐
│ USER CRONTAB (crontab -e) │
│ │
│ 0 3 * * * /path/script.sh │
│ │ │ │ │ │ │
│ │ │ │ │ └── day of week │
│ │ │ │ └──── month │
│ │ │ └────── day of month │
│ │ └──────── hour │
│ └────────── minute │
│ Runs as the user who owns the crontab. │
│ No username field. │
│ │
│ SYSTEM CRONTAB (/etc/crontab) │
│ │
│ 0 3 * * * mary /path/script.sh │
│ │ │
│ └── username (runs as mary) │
│ Runs as the specified user. │
│ │
└──────────────────────────────────────────────┘
Cron Execution Flow
┌──────────────────────────────────────────────┐
│ CRON DAEMON │
│ │
│ Every minute: │
│ Read /etc/crontab │
│ Read /etc/cron.d/* │
│ Read user crontabs │
│ │ │
│ ▼ │
│ For each job: │
│ Do time fields match now? │
│ ├── Yes → execute command │
│ └── No → skip │
│ │
│ Output: │
│ MAILTO set → email │
│ Redirected → log file │
│ Neither → lost │
│ │
└──────────────────────────────────────────────┘
Special Characters
┌──────────────────────────────────────────────┐
│ FIELD SYNTAX │
│ │
│ * = every value │
│ */15 = every 15 (step) │
│ │
│ , = list │
│ 1,15 = 1st and 15th │
│ │
│ - = range │
│ 9-17 = 9 through 17 │
│ │
│ / = step │
│ */10 = 0,10,20,30,40,50 │
│ │
│ Example: │
│ */15 9-17 * * 1-5 │
│ = every 15 min, 9 AM–5 PM, weekdays │
│ │
└──────────────────────────────────────────────┘
Verification Flow
┌──────────────────────────────────────────────┐
│ DID THE JOB RUN? │
│ │
│ 1. crontab -l │
│ → Job is installed? │
│ │
│ 2. grep CRON /var/log/syslog │
│ → Execution logged? │
│ │
│ 3. tail /var/log/job.log │
│ → Output captured? │
│ │
│ If no log entry: │
│ → PATH wrong │
│ → Syntax error (blank field) │
│ → Cron daemon not running │
│ │
└──────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Time fields | minute, hour, day, month, weekday |
| Field ranges | 0–59, 0–23, 1–31, 1–12, 0–7 |
| Sunday | 0 or 7 |
| User crontab | 5 fields + command, runs as owner |
| System crontab | 5 fields + username + command |
| Edit user crontab | crontab -e |
| List user crontab | crontab -l |
| System crontab file | /etc/crontab, /etc/cron.d/ |
| Default PATH | /usr/bin:/bin (set explicitly) |
| Output | Redirect to log; MAILTO for email |
Key takeaways:
- A user crontab has five time fields and a command; a system crontab adds a username field. The username field is what allows a system crontab entry to run as a non-root user. Confusing the two formats is the primary exam trap .
- The five time fields are minute, hour, day of month, month, and day of week. Each has a fixed range, and a blank field breaks the entry silently.
*matches every value,,lists,-ranges, and/steps . - Cron runs with a minimal environment.
PATHis typically/usr/bin:/bin, and the shell is/bin/sh. Scripts that work interactively may fail in cron because they rely on aPATHentry or variable that is absent. SetPATHandSHELLat the top of the crontab, or use absolute paths . - Output must be redirected or it is lost. Cron emails output if
MAILTOis set and an MTA is configured; otherwise, it goes to the local mail spool or is discarded. Redirecting to a log file is the exam-safe approach. - Verification is two steps.
crontab -lconfirms installation, and the system log (/var/log/syslogor/var/log/cron) confirms execution. The job’s own log shows the output . - The system crontab is edited with a text editor, not
crontab -e. The/etc/crontabfile and/etc/cron.d/files use the six-field format. Thecrontabcommand manages only user crontabs.
Remember: Traditional cron is a five-field scheduler with a single daemon and a minimal environment. The five fields are minute, hour, day, month, and weekday. A user crontab runs as the user who owns it and has no username field. A system crontab adds a username field and runs the command as that user. The exam tests both formats, the special characters that make the fields flexible, and the verification steps that confirm a job ran. Absolute paths, explicit PATH settings, and output redirection are not optional—they are the difference between a job that works and one that fails silently in the minimal cron environment.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!