Cron and Systemd Timers: Schedule Tasks the Linux Way

Have you ever wanted your computer to automatically run a task at a specific time? Maybe backup your files every night, send yourself a reminder email on Mondays, or clean up temporary files every week? In Linux, you can automate these tasks using two powerful tools: Cron and Systemd Timers.

Think of these tools as your personal assistant that never forgets to do repetitive tasks for you!

What is Task Scheduling?

Task scheduling is simply telling your computer to run a program or command at specific times automatically. Instead of manually running a backup script every day, you can schedule it to run at 2 AM when you’re sleeping.

Common examples include:

  • Backing up important files daily
  • Cleaning temporary files weekly
  • Sending system reports monthly
  • Updating software automatically
  • Restarting services at specific intervals

Now let’s explore the two main ways to schedule tasks in Linux.


Part 1: Cron - The Traditional Way

Cron (short for “chronograph”) has been the go-to task scheduler in Unix-like systems for decades. It’s like having a very reliable alarm clock that can run any command you want.

How Cron Works

Cron runs as a background service (called a “daemon”) that checks every minute if there are any scheduled tasks to execute. These scheduled tasks are stored in files called “crontabs” (cron tables).

Understanding Cron Syntax

Cron uses a specific format to define when tasks should run. It might look confusing at first, but it follows a simple pattern:

1
2
3
4
5
6
7
* * * * * command-to-run
| | | | |
| | | | └── Day of week (0-7, where 0 and 7 are Sunday)
| | | └──── Month (1-12)
| | └────── Day of month (1-31)
| └──────── Hour (0-23)
└────────── Minute (0-59)

Each * means “every” - so * * * * * means “every minute of every hour of every day.”

Cron Examples

Let’s look at some practical examples:

Run a backup script every day at 2:30 AM:

1
30 2 * * * /home/user/backup.sh

Send a report every Monday at 9 AM:

1
0 9 * * 1 /home/user/send-report.sh

Clean temporary files every Sunday at midnight:

1
0 0 * * 0 rm -rf /tmp/*

Check disk space every 30 minutes:

1
*/30 * * * * df -h > /home/user/disk-usage.log

Working with Cron

View your current cron jobs:

1
crontab -l

Edit your cron jobs:

1
crontab -e

This opens a text editor where you can add, modify, or remove scheduled tasks.

Remove all your cron jobs:

1
crontab -r

Cron Shortcuts

Cron provides some handy shortcuts for common schedules:

  • @yearly or @annually - Run once a year (same as 0 0 1 1 *)
  • @monthly - Run once a month (same as 0 0 1 * *)
  • @weekly - Run once a week (same as 0 0 * * 0)
  • @daily or @midnight - Run once a day (same as 0 0 * * *)
  • @hourly - Run once an hour (same as 0 * * * *)
  • @reboot - Run at system startup

Example using shortcuts:

1
2
3
@daily /home/user/backup.sh
@weekly /home/user/cleanup.sh
@reboot /home/user/startup-script.sh

Your First Cron Job - A Complete Example

Let’s create your first scheduled task using cron:

Step 1: Create a simple script

1
2
3
4
5
6
# Create the script file
echo '#!/bin/bash
echo "Hello from cron! $(date)" >> /home/$USER/cron-test.log' > /home/$USER/hello-cron.sh

# Make it executable
chmod +x /home/$USER/hello-cron.sh

Step 2: Test the script manually

1
2
3
4
5
# Run it once to make sure it works
/home/$USER/hello-cron.sh

# Check if it created the log file
cat /home/$USER/cron-test.log

Step 3: Schedule it with cron

1
2
3
4
5
# Edit your crontab
crontab -e

# Add this line (runs every minute for testing)
* * * * * /home/$USER/hello-cron.sh

Step 4: Wait and check results After a minute or two, check the log file:

1
cat /home/$USER/cron-test.log

You should see multiple timestamps showing when the script ran!

Step 5: Remove the test job

1
2
# Edit crontab again and remove the line
crontab -e

Now you understand how cron works! Let’s move on to the modern alternative.


Part 2: Systemd Timers - The Modern Alternative

Systemd is a newer system management tool that’s now standard on most Linux distributions. Systemd timers are the modern replacement for cron jobs, offering more features and better integration with the system.

Why Use Systemd Timers?

While cron is simple and works well, systemd timers offer several advantages:

  • Better logging: Easier to see what happened and debug issues
  • Dependencies: Can wait for other services to start first
  • Resource control: Can limit CPU, memory usage
  • More flexible scheduling: Can handle complex timing requirements
  • System integration: Works seamlessly with other systemd services

How Systemd Timers Work

This is the key difference from cron: systemd timers require TWO separate files that work together:

  1. Service file (.service) - Defines WHAT to run
  2. Timer file (.timer) - Defines WHEN to run it

Think of it this way: the service file is like writing down instructions for a task, and the timer file is like setting an alarm clock to remind you to do that task.

Creating Your First Systemd Timer

Let’s create a complete example step by step. We’ll make a backup timer that runs daily.

Step 1: Create the Service File

The service file defines what command to run. Let’s create backup.service:

First, create the file:

1
nano ~/backup.service

Add this content:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[Unit]
Description=Daily Backup Service
After=network.target

[Service]
Type=oneshot
User=myuser
WorkingDirectory=/home/myuser
Environment=PATH=/usr/local/bin:/usr/bin:/bin
ExecStart=/home/myuser/backup.sh
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Understanding the Service File:

[Unit] Section - Basic Information

  • Description= - Human-readable description of what this service does
  • After=network.target - Wait for network to be available before running

[Service] Section - What Actually Runs

  • Type=oneshot - This task runs once and then finishes (perfect for scheduled tasks)
  • User=myuser - Run as your user (replace “myuser” with your actual username)
  • WorkingDirectory= - Set the working directory for the script
  • Environment=PATH= - Set environment variables
  • ExecStart= - The actual command to run (must be full path)
  • StandardOutput=journal - Send output to systemd’s logging system
  • StandardError=journal - Send errors to systemd’s logging system

[Install] Section - System Integration

  • WantedBy=multi-user.target - When this service should be available

Step 2: Create the Timer File

Now we create the timer file that tells systemd when to run our service. Let’s create backup.timer:

Create the timer file:

1
nano ~/backup.timer

Add this content:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[Unit]
Description=Run backup daily
Requires=backup.service

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Understanding the Timer File:

[Unit] Section

  • Description= - What this timer does
  • Requires=backup.service - This timer needs the backup service to exist

[Timer] Section - The Scheduling

  • OnCalendar=daily - Run every day at midnight
  • Persistent=true - If the system was off when the timer should have run, run it when the system starts

[Install] Section

  • WantedBy=timers.target - This timer should start with the timer system

Step 3: Install the Timer

Now we need to install both files and activate the timer:

Copy files to systemd directory:

1
2
sudo cp ~/backup.service /etc/systemd/system/
sudo cp ~/backup.timer /etc/systemd/system/

Reload systemd to recognize new files:

1
sudo systemctl daemon-reload

Enable and start the timer:

1
2
sudo systemctl enable backup.timer
sudo systemctl start backup.timer

Step 4: Verify Everything Works

Check timer status:

1
systemctl status backup.timer

List all active timers:

1
systemctl list-timers

Test the service manually:

1
2
sudo systemctl start backup.service
sudo systemctl status backup.service

View logs:

1
2
journalctl -u backup.timer
journalctl -u backup.service

Systemd Timer Schedule Formats

Systemd uses a more human-readable format for scheduling than cron:

Common Examples:

  • OnCalendar=daily - Every day at midnight
  • OnCalendar=weekly - Every Sunday at midnight
  • OnCalendar=monthly - First day of every month at midnight
  • OnCalendar=*-*-* 02:30:00 - Every day at 2:30 AM
  • OnCalendar=Mon *-*-* 09:00:00 - Every Monday at 9 AM
  • OnCalendar=*-*-01 00:00:00 - First day of every month

Managing Systemd Timers

List all timers:

1
systemctl list-timers

Check specific timer status:

1
systemctl status backup.timer

View timer logs:

1
2
journalctl -u backup.timer
journalctl -u backup.service

Stop a timer:

1
sudo systemctl stop backup.timer

Disable a timer:

1
sudo systemctl disable backup.timer

Remove timer files:

1
2
3
sudo rm /etc/systemd/system/backup.timer
sudo rm /etc/systemd/system/backup.service
sudo systemctl daemon-reload

Part 3: Cron vs Systemd Timers - Which Should You Choose?

Choose Cron if:

  • You want something simple and quick to set up
  • You’re working on older systems
  • You need basic scheduling without complex requirements
  • You’re comfortable with the traditional cron syntax
  • You want something that works the same way across different Unix systems

Choose Systemd Timers if:

  • You want better logging and debugging capabilities
  • You need dependencies (wait for network, other services)
  • You want resource control (CPU/memory limits)
  • You’re building more complex automation workflows
  • You prefer modern, well-integrated tools
  • You’re working primarily on modern Linux distributions

Part 4: Practical Tips for Beginners

1. Start Simple

Begin with basic tasks like creating log files or simple backups before moving to complex scripts.

2. Test Your Commands First

Always test your commands manually before scheduling them:

1
2
3
4
# Test the command works
/home/user/backup.sh

# Then add to cron or systemd

3. Use Full Paths

Always use complete file paths in your scheduled tasks:

1
2
3
4
5
# Good
/usr/bin/python3 /home/user/script.py

# Bad (might not work in scheduled context)
python3 script.py

4. Handle Output and Errors

Redirect output to files so you can check if things worked:

For Cron:

1
2
# Save both normal output and errors to a log file
0 2 * * * /home/user/backup.sh >> /home/user/backup.log 2>&1

For Systemd: (Output automatically goes to journal)

1
2
# View the logs
journalctl -u backup.service

5. Set Environment Variables

Scheduled tasks run with minimal environment. Set important variables:

For Cron:

1
2
3
# In crontab, set PATH at the top
PATH=/usr/local/bin:/usr/bin:/bin
0 2 * * * /home/user/backup.sh

For Systemd: (Use Environment= in service file)

1
2
[Service]
Environment=PATH=/usr/local/bin:/usr/bin:/bin

Part 5: Common Gotchas to Avoid

Environment Differences

Scheduled tasks run in a different environment than your interactive shell. Commands that work in your terminal might fail when scheduled because:

  • Different PATH variable
  • Missing environment variables
  • Different working directory

Permissions

Make sure:

  • Your scripts are executable (chmod +x script.sh)
  • You have permission to read/write files the script uses
  • System-wide timers may need sudo privileges

Time Zones

Both cron and systemd use the system’s local time zone. If you change time zones or deal with daylight saving time, be aware this might affect your schedules.

Testing is Crucial

Always test your scheduled tasks manually before setting them to run automatically. This catches most problems early.


Conclusion

Task scheduling is a powerful way to automate repetitive tasks in Linux. Whether you choose the traditional cron or modern systemd timers, both tools can help you create a more efficient and automated system.

Quick Summary:

  • Cron: Simple, traditional, works everywhere, good for basic scheduling
  • Systemd Timers: Modern, powerful, better logging, good for complex scenarios

Start with simple tasks, test everything manually first, and gradually build more complex automation as you become comfortable with the tools. Remember, the goal is to make your life easier by letting the computer handle routine tasks while you focus on more important things.

The key to success is starting small, testing thoroughly, and building up your automation skills step by step. Happy scheduling!