Special Cron Strings (@reboot, @daily, @hourly)
In this tutorial, you will learn about Special Cron Strings (@reboot, @daily, @hourly). We cover key concepts, practical examples, and best practices to help you master this topic.
Use special cron strings like @reboot, @daily, @hourly, @monthly, and @yearly for simpler scheduling without writing five-field expressions every time.
What You Learn
You will learn the eight special cron strings (@reboot, @yearly, @annually, @monthly, @weekly, @daily, @midnight, @hourly), their five-field equivalents, when to use each, and portability considerations.
Why It Matters
Special strings make crontabs more readable. @daily is clearer than 0 0 * * *. They reduce syntax errors and make schedule intent obvious. However, not all cron implementations support them.
Real-World Use
DodaTech uses @reboot to start monitoring agents, @daily for database backups, @hourly for cache warming, and @weekly for analytics reports. Special strings cover 80% of their scheduling needs.
Available Special Strings
# @reboot: Run once when cron daemon starts (at system boot)
@reboot /opt/scripts/startup_checks.sh
@reboot /usr/bin/python3 /opt/agents/monitor.py
# @yearly or @annually: Run once a year (0 0 1 1 *)
@yearly /opt/scripts/cert_renewal.sh
@annually /opt/scripts/yearly_audit.py
# @monthly: Run once a month (0 0 1 * *)
@monthly /opt/scripts/monthly_billing.py
@monthly /opt/scripts/log_archive.sh
# @weekly: Run once a week (0 0 * * 0)
@weekly /opt/scripts/weekly_report.sh
@weekly /opt/scripts/db_optimize.py
# @daily or @midnight: Run once a day (0 0 * * *)
@daily /opt/scripts/daily_backup.sh
@midnight /opt/scripts/log_rotation.py
# @hourly: Run once an hour (0 * * * *)
@hourly /opt/scripts/cache_warm.sh
@hourly /opt/scripts/health_ping.py
Five-Field Equivalents
special_strings = {
'@reboot': None, # Runs at startup, no time equivalent
'@yearly': '0 0 1 1 *',
'@annually': '0 0 1 1 *',
'@monthly': '0 0 1 * *',
'@weekly': '0 0 * * 0',
'@daily': '0 0 * * *',
'@midnight': '0 0 * * *',
'@hourly': '0 * * * *',
}
def explain_special(special):
if special in special_strings:
equiv = special_strings[special]
if equiv:
print(f"{special:12s} = {equiv:15s} (five-field equivalent)")
else:
print(f"{special:12s} = runs at system boot only")
else:
print(f"Unknown special string: {special}")
for s in ['@daily', '@reboot', '@weekly', '@yearly']:
explain_special(s)
Expected output:
@daily = 0 0 * * * (five-field equivalent)
@reboot = runs at system boot only
@weekly = 0 0 * * 0 (five-field equivalent)
@yearly = 0 0 1 1 * (five-field equivalent)
@reboot Deep Dive
# @reboot runs when the cron daemon starts.
# This typically happens at system boot, but also if cron is restarted.
# Use @reboot for:
@reboot /usr/local/bin/start_web_server.sh
@reboot /usr/bin/python3 /opt/agents/register.py
@reboot sleep 10 && /opt/scripts/delayed_startup.sh
# Caution: @reboot does NOT run on user login.
# It runs when crond starts, which is once at boot.
# To delay @reboot execution:
@reboot sleep 30 && /opt/scripts/wait_for_network.sh
# Check if @reboot jobs ran:
grep -i "reboot\|startup" /var/log/syslog | tail -5
@reboot vs systemd
# @reboot in cron is simple but limited.
# For complex startup logic, use systemd:
# /etc/systemd/system/my-startup.service
# [Unit]
# Description=My Startup Service
# After=network.target
#
# [Service]
# Type=oneshot
# ExecStart=/opt/scripts/startup.sh
# RemainAfterExit=yes
#
# [Install]
# WantedBy=multi-user.target
# Enable the service
sudo systemctl enable my-startup.service
sudo systemctl start my-startup.service
# Compare with cron @reboot:
# systemd: dependency management, logging, restart policies
# cron @reboot: simple, no dependencies, runs once
Portability Issues
import os
import subprocess
def check_cron_support():
"""Check if the current cron implementation supports special strings."""
try:
result = subprocess.run(
['crontab', '-l'],
capture_output=True, text=True
)
crontab_content = result.stdout
specials = ['@reboot', '@daily', '@hourly', '@weekly', '@monthly', '@yearly']
supported = []
for s in specials:
# Test by attempting to install a temporary crontab
test_cron = f"{s} echo test\n"
test_result = subprocess.run(
['crontab', '-'],
input=test_cron,
capture_output=True, text=True
)
if test_result.returncode == 0:
supported.append(s)
return supported
except Exception as e:
return f"Error: {e}"
# Check if Docker/container cron supports special strings
# Many minimal Docker images use busybox cron which lacks @reboot
# Always test in your target environment
Mixing Special Strings with Regular Syntax
# Crontab mixing special strings and regular expressions
# Special strings for common schedules
@daily /opt/scripts/backup.sh
@hourly /opt/scripts/health.sh
# Regular expressions for precise needs
30 8 * * 1-5 /opt/scripts/business_hours.py
0 0 1 */3 * /opt/scripts/quarterly_report.sh
*/15 9-17 * * 1-5 /opt/scripts/detailed_monitor.py
# @reboot for startup tasks
@reboot /opt/scripts/init_services.sh
Common Mistakes
1. Assuming @reboot Runs on User Login
@reboot runs when crond starts, not when a user logs in. For login scripts, use .bashrc or .profile.
2. Using @reboot in Docker Containers
Many Docker base images use busybox cron which does not support @reboot. Use an ENTRYPOINT script instead.
3. Special Strings in Non-Standard Cron
Not all cron implementations (busybox, anacron, systemd timers) support special strings. Expand to five-field equivalents for portability.
4. Forgetting @reboot Runs Once
@reboot tasks run only when cron starts. If cron is already running, adding a @reboot job does not execute it until the next restart.
5. Mixing @reboot with Time Fields
@reboot is a special string, not a field. Do not add time fields after it. @reboot 0 3 * * * command is invalid.
Practice Questions
1. What is the five-field equivalent of @weekly?
0 0 * * 0 (midnight every Sunday).
2. When does @reboot execute?
When the cron daemon starts, which is typically at system boot. It does not run on user login or at a specific time.
3. What is the difference between @daily and @midnight?
None. Both expand to 0 0 * * *. @midnight is an alias for @daily.
4. Why might @reboot not work in Docker?
Docker containers often use busybox cron which lacks @reboot support. Use a startup script in the container ENTRYPOINT instead.
Challenge
Create a crontab that uses only special strings for: database backup (daily), cache warming (hourly), certificate renewal (yearly), log archiving (weekly), monitoring agent startup (at boot), and billing report (monthly). Then convert all special strings to their five-field equivalents.
FAQ
Mini Project: Special Strings Crontab
# /etc/cron.d/my-schedules
# Special strings make intent clear
# Startup monitoring agent
@reboot root /usr/local/bin/start-monitor.sh
# Hourly cache warming
@hourly root /usr/local/bin/warm-cache.sh
# Daily security scan
@daily root /usr/local/bin/security-scan.sh
# Weekly report generation
@weekly root /usr/local/bin/generate-report.py
# Monthly log archiving
@monthly root /usr/local/bin/archive-logs.sh
# Yearly certificate renewal reminder
@yearly root /usr/local/bin/renew-certs.sh
# Equivalent five-field version (uncomment to replace above):
# 0 * * * * root /usr/local/bin/warm-cache.sh
# 0 0 * * * root /usr/local/bin/security-scan.sh
# 0 0 * * 0 root /usr/local/bin/generate-report.py
# 0 0 1 * * root /usr/local/bin/archive-logs.sh
# 0 0 1 1 * root /usr/local/bin/renew-certs.sh
What's Next
Now that you understand special cron strings, explore crontab file management for editing and managing Cron Jobs, then learn about environment variables in cron for script configuration.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro