cron-schedulingSchedule and manage recurring tasks with cron and systemd timers. Use when setting up cron jobs, writing systemd timer units, handling timezone-aware scheduling, monitoring failed jobs, implementing retry patterns, or debugging why a scheduled task didn't run.
Install via ClawdBot CLI:
clawdbot install gitgoodordietrying/cron-schedulingSchedule and manage recurring tasks. Covers cron syntax, crontab management, systemd timers, one-off scheduling, timezone handling, monitoring, and common failure patterns.
āāāāāāāāāā minute (0-59)
ā āāāāāāāā hour (0-23)
ā ā āāāāāā day of month (1-31)
ā ā ā āāāā month (1-12 or JAN-DEC)
ā ā ā ā āā day of week (0-7, 0 and 7 = Sunday, or SUN-SAT)
ā ā ā ā ā
* * * * * command
# Every minute
* * * * * /path/to/script.sh
# Every 5 minutes
*/5 * * * * /path/to/script.sh
# Every hour at :00
0 * * * * /path/to/script.sh
# Every day at 2:30 AM
30 2 * * * /path/to/script.sh
# Every Monday at 9:00 AM
0 9 * * 1 /path/to/script.sh
# Every weekday at 8:00 AM
0 8 * * 1-5 /path/to/script.sh
# First day of every month at midnight
0 0 1 * * /path/to/script.sh
# Every 15 minutes during business hours (Mon-Fri 9-17)
*/15 9-17 * * 1-5 /path/to/script.sh
# Twice a day (9 AM and 5 PM)
0 9,17 * * * /path/to/script.sh
# Every quarter (Jan, Apr, Jul, Oct) on the 1st at midnight
0 0 1 1,4,7,10 * /path/to/script.sh
# Every Sunday at 3 AM
0 3 * * 0 /path/to/script.sh
@reboot /path/to/script.sh # Run once at startup
@yearly /path/to/script.sh # 0 0 1 1 *
@monthly /path/to/script.sh # 0 0 1 * *
@weekly /path/to/script.sh # 0 0 * * 0
@daily /path/to/script.sh # 0 0 * * *
@hourly /path/to/script.sh # 0 * * * *
# Edit current user's crontab
crontab -e
# List current crontab
crontab -l
# Edit another user's crontab (root)
sudo crontab -u www-data -e
# Remove all cron jobs (be careful!)
crontab -r
# Install crontab from file
crontab mycrontab.txt
# Backup crontab
crontab -l > crontab-backup-$(date +%Y%m%d).txt
# Set PATH explicitly (cron has minimal PATH)
PATH=/usr/local/bin:/usr/bin:/bin
# Set MAILTO for error notifications
MAILTO=admin@example.com
# Set shell explicitly
SHELL=/bin/bash
# Full crontab example
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com
SHELL=/bin/bash
# Backups
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
# Cleanup old logs
0 3 * * 0 find /var/log/myapp -name "*.log" -mtime +30 -delete
# Health check
*/5 * * * * /opt/scripts/healthcheck.sh || /opt/scripts/alert.sh "Health check failed"
# /etc/systemd/system/backup.service
[Unit]
Description=Daily backup
[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh
User=backup
StandardOutput=journal
StandardError=journal
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 2 AM
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
# Enable and start the timer
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
# Check timer status
systemctl list-timers
systemctl list-timers --all
# Check last run
systemctl status backup.service
journalctl -u backup.service --since today
# Run manually (for testing)
sudo systemctl start backup.service
# Disable timer
sudo systemctl disable --now backup.timer
# Systemd calendar expressions
# Daily at midnight
OnCalendar=daily
# or: OnCalendar=*-*-* 00:00:00
# Every Monday at 9 AM
OnCalendar=Mon *-*-* 09:00:00
# Every 15 minutes
OnCalendar=*:0/15
# Weekdays at 8 AM
OnCalendar=Mon..Fri *-*-* 08:00:00
# First of every month
OnCalendar=*-*-01 00:00:00
# Every 6 hours
OnCalendar=0/6:00:00
# Specific dates
OnCalendar=2026-02-03 12:00:00
# Test calendar expressions
systemd-analyze calendar "Mon *-*-* 09:00:00"
systemd-analyze calendar "*:0/15"
systemd-analyze calendar --iterations=5 "Mon..Fri *-*-* 08:00:00"
Systemd timers vs cron:
+ Logs in journald (journalctl -u service-name)
+ Persistent: catches up on missed runs after reboot
+ RandomizedDelaySec: prevents thundering herd
+ Dependencies: can depend on network, mounts, etc.
+ Resource limits: CPUQuota, MemoryMax, etc.
+ No lost-email problem (MAILTO often misconfigured)
- More files to create (service + timer)
- More verbose configuration
# Schedule a command
echo "/opt/scripts/deploy.sh" | at 2:00 AM tomorrow
echo "reboot" | at now + 30 minutes
echo "/opt/scripts/report.sh" | at 5:00 PM Friday
# Interactive (type commands, Ctrl+D to finish)
at 10:00 AM
> /opt/scripts/task.sh
> echo "Done" | mail -s "Task complete" admin@example.com
> <Ctrl+D>
# List pending jobs
atq
# View job details
at -c <job-number>
# Remove a job
atrm <job-number>
# Run something after a delay
(sleep 3600 && /opt/scripts/task.sh) &
# With nohup (survives logout)
nohup bash -c "sleep 7200 && /opt/scripts/task.sh" &
# Cron runs in the system timezone by default
# Check system timezone
timedatectl
date +%Z
# Set timezone for a specific cron job
# Method 1: TZ variable in crontab
TZ=America/New_York
0 9 * * * /opt/scripts/report.sh
# Method 2: In the script itself
#!/bin/bash
export TZ=UTC
# All date operations now use UTC
# Method 3: Wrapper
TZ=Europe/London date '+%Y-%m-%d %H:%M:%S'
# List available timezones
timedatectl list-timezones
timedatectl list-timezones | grep America
Problem: A job scheduled for 2:30 AM may run twice or not at all
during DST transitions.
"Spring forward": 2:30 AM doesn't exist (clock jumps 2:00 ā 3:00)
"Fall back": 2:30 AM happens twice
Mitigation:
1. Schedule critical jobs outside 1:00-3:00 AM
2. Use UTC for the schedule: TZ=UTC in crontab
3. Make jobs idempotent (safe to run twice)
4. Systemd timers handle DST correctly
# 1. Check cron daemon is running
systemctl status cron # Debian/Ubuntu
systemctl status crond # CentOS/RHEL
# 2. Check cron logs
grep CRON /var/log/syslog # Debian/Ubuntu
grep CRON /var/log/cron # CentOS/RHEL
journalctl -u cron --since today # systemd
# 3. Check crontab actually exists
crontab -l
# 4. Test the command manually (with cron's environment)
env -i HOME=$HOME SHELL=/bin/sh PATH=/usr/bin:/bin /opt/scripts/backup.sh
# If it fails here but works normally ā PATH or env issue
# 5. Check permissions
ls -la /opt/scripts/backup.sh # Must be executable
ls -la /var/spool/cron/ # Crontab file permissions
# 6. Check for syntax errors in crontab
# cron silently ignores lines with errors
# 7. Check if output is being discarded
# By default, cron emails output. If no MTA, output is lost.
# Always redirect: >> /var/log/myjob.log 2>&1
#!/bin/bash
# cron-wrapper.sh ā Run a command with logging, timing, and error alerting
# Usage: cron-wrapper.sh <job-name> <command> [args...]
set -euo pipefail
JOB_NAME="${1:?Usage: cron-wrapper.sh <job-name> <command> [args...]}"
shift
COMMAND=("$@")
LOG_DIR="/var/log/cron-jobs"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/$JOB_NAME.log"
log() { echo "[$(date -u '+%Y-%m-%dT%H:%M:%SZ')] $*" >> "$LOG_FILE"; }
log "START: ${COMMAND[*]}"
START_TIME=$(date +%s)
if "${COMMAND[@]}" >> "$LOG_FILE" 2>&1; then
ELAPSED=$(( $(date +%s) - START_TIME ))
log "SUCCESS (${ELAPSED}s)"
else
EXIT_CODE=$?
ELAPSED=$(( $(date +%s) - START_TIME ))
log "FAILED with exit code $EXIT_CODE (${ELAPSED}s)"
# Alert (customize as needed)
echo "Cron job '$JOB_NAME' failed with exit $EXIT_CODE" | \
mail -s "CRON FAIL: $JOB_NAME" admin@example.com 2>/dev/null || true
exit $EXIT_CODE
fi
# Use in crontab:
0 2 * * * /opt/scripts/cron-wrapper.sh daily-backup /opt/scripts/backup.sh
*/5 * * * * /opt/scripts/cron-wrapper.sh health-check /opt/scripts/healthcheck.sh
# Prevent concurrent runs (job takes longer than interval)
# Method 1: flock
* * * * * flock -n /tmp/myjob.lock /opt/scripts/slow-job.sh
# Method 2: In the script
LOCKFILE="/tmp/myjob.lock"
exec 200>"$LOCKFILE"
flock -n 200 || { echo "Already running"; exit 0; }
# ... do work ...
# Idempotent backup (only creates if newer than last backup)
#!/bin/bash
BACKUP_DIR="/backups/$(date +%Y%m%d)"
[[ -d "$BACKUP_DIR" ]] && { echo "Backup already exists"; exit 0; }
mkdir -p "$BACKUP_DIR"
pg_dump mydb > "$BACKUP_DIR/mydb.sql"
# Idempotent cleanup (safe to run multiple times)
find /tmp/uploads -mtime +7 -type f -delete 2>/dev/null || true
# Idempotent sync (rsync only transfers changes)
rsync -az /data/ backup-server:/backups/data/
>> /var/log/job.log 2>&1. Without this, output goes to mail (if configured) or is silently lost.env -i to simulate cron's minimal environment. Most failures are caused by missing PATH or environment variables.flock to prevent overlapping runs when a job might take longer than its schedule interval.systemd-analyze calendar is invaluable for verifying timer schedules before deploying.Persistent=true), and resource limits for free.Generated Mar 1, 2026
Schedule daily or weekly database backups during off-peak hours to ensure data integrity and disaster recovery. Use cron jobs to run backup scripts that export databases to secure storage, with logging and failure alerts via email or monitoring systems.
Generate sales and inventory reports automatically at the end of each business day using cron. This helps in tracking performance, managing stock levels, and providing insights without manual intervention, improving operational efficiency.
Set up recurring tasks with cron or systemd timers to run health checks every few minutes, monitoring server resources and application status. Failed checks trigger alerts or retry mechanisms, ensuring high availability and quick issue resolution.
Automate the cleanup of old log files on a weekly basis using cron jobs to prevent disk space issues. Schedule scripts that archive or delete logs older than a set period, maintaining system performance and compliance with data retention policies.
Use cron to trigger email campaigns at specific times, such as morning newsletters or promotional blasts during peak hours. This ensures timely delivery to customers, optimizing engagement rates and marketing ROI.
Offer a cloud-based scheduling service with a subscription model, providing users with an intuitive interface to manage cron jobs and systemd timers. Revenue comes from monthly or annual fees, with tiers based on features like advanced monitoring and support.
Provide consulting services to businesses for setting up and optimizing scheduled tasks, including cron and systemd timer configurations. Revenue is generated through project-based fees or hourly rates for customization, training, and troubleshooting.
Bundle scheduling tools into managed hosting packages, where clients pay for server management that includes automated backups, monitoring, and task scheduling. Revenue streams include hosting fees and add-ons for premium automation features.
š¬ Integration Tip
Integrate with monitoring tools like Nagios or Prometheus to track job failures and set up alerts. Use environment variables in cron jobs for flexibility across different deployment environments.
A fast Rust-based headless browser automation CLI with Node.js fallback that enables AI agents to navigate, click, type, and snapshot pages via structured commands.
Automate web browser interactions using natural language via CLI commands. Use when the user asks to browse websites, navigate web pages, extract data from websites, take screenshots, fill forms, click buttons, or interact with web applications.
Advanced desktop automation with mouse, keyboard, and screen control
Manage n8n workflows and automations via API. Use when working with n8n workflows, executions, or automation tasks - listing workflows, activating/deactivating, checking execution status, manually triggering workflows, or debugging automation issues.
Design and implement automation workflows to save time and scale operations as a solopreneur. Use when identifying repetitive tasks to automate, building workflows across tools, setting up triggers and actions, or optimizing existing automations. Covers automation opportunity identification, workflow design, tool selection (Zapier, Make, n8n), testing, and maintenance. Trigger on "automate", "automation", "workflow automation", "save time", "reduce manual work", "automate my business", "no-code automation".
Browser automation via Playwright MCP server. Navigate websites, click elements, fill forms, extract data, take screenshots, and perform full browser automation workflows.