scron/README.md
kekskurse c5198ed241
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
docs: weekday in readme and sample config
2025-08-06 18:36:25 +02:00

8.8 KiB

SCRON

A lightweight, efficient cron-like scheduler written in Go that executes shell commands at specified intervals with precise timing, comprehensive logging, and flexible notification support.

Features

  • 🕐 Flexible Scheduling: Advanced cron-like time patterns with minute-level precision
  • 🔄 Dynamic Configuration: Automatic config reloading without restart
  • 📊 Structured Logging: JSON-formatted logs with zerolog for easy parsing
  • 🔔 Multi-Channel Notifications: Support for Gotify and SMTP notifications
  • Concurrent Execution: Jobs run in parallel for optimal performance
  • 🛡️ Robust Error Handling: Comprehensive error tracking with exit codes
  • 📝 Output Capture: Combined stdout/stderr capture for debugging

Installation

From Source

# Clone the repository
git clone https://github.com/yourusername/scron.git
cd scron

# Build the binary
go build -o scron ./

# Run
./scron

Debian Package

Download the latest .deb package from the releases page:

# Install package
sudo dpkg -i scron_X.X.X_linux_amd64.deb

Configuration file location: /etc/scron/config.yml

Configuration

Create a config.yml file in the same directory as the binary (or /etc/scron/ for package installations):

Basic Configuration

Optionally, you can specify the weekday field (0=Sunday, 1=Monday, ..., 6=Saturday) to restrict jobs to specific days of the week.

jobs:
  - name: "System Health Check"
    minute: "*/5"
    hour: "*"
    weekday: "*"
    command: "curl -f http://localhost:8080/health || exit 1"
  
  - name: "Daily Backup"
    minute: "0"
    hour: "2"
    weekday: "*"
    command: "/usr/local/bin/backup.sh"

Advanced Configuration with Notifications

# Notification configurations
notification:
  - name: default
    success:
      gotify:
        url: "https://gotify.example.com/message?token=YOUR_TOKEN"
      smtp:
        host: "smtp.gmail.com"
        port: 587
        username: "your-email@gmail.com"
        password: "your-app-password"
        from: "scron@example.com"
        to: "admin@example.com"
        use_ssl: true
    error:
      gotify:
        url: "https://gotify.example.com/message?token=YOUR_CRITICAL_TOKEN"
      smtp:
        host: "smtp.gmail.com"
        port: 587
        username: "your-email@gmail.com"
        password: "your-app-password"
        from: "scron-alerts@example.com"
        to: "oncall@example.com"
        use_ssl: true

  - name: critical-only
    error:
      gotify:
        url: "https://gotify.example.com/message?token=YOUR_CRITICAL_TOKEN"

# Job definitions
jobs:
  - name: "Database Backup"
    minute: "0"
    hour: "3"
    weekday: "*"
    command: "pg_dump mydb > /backup/mydb_$(date +%Y%m%d).sql"
    notification: default
  
  - name: "Critical Service Monitor"
    minute: "*/1"
    hour: "*"
    weekday: "*"
    command: "systemctl is-active nginx || exit 1"
    notification: critical-only

Time Pattern Syntax (minute, hour, and optional weekday)

SCRON supports flexible cron-like time patterns for minutes (0-59), hours (0-23), and optional weekdays (0-6). 0 is Sunday, 1 is Monday, and so on:

Pattern Description Example
* Every minute/hour minute: "*" - every minute
n Specific value hour: "14" - at 2 PM
*/n Every n intervals minute: "*/15" - every 15 minutes
n,m Multiple values hour: "9,12,17" - at 9 AM, noon, and 5 PM
n-m Range (inclusive) hour: "9-17" - 9 AM to 5 PM
n-m/s Range with step minute: "10-50/10" - at 10, 20, 30, 40, 50
n-m,x-y Multiple ranges hour: "0-6,20-23" - night hours

Pattern Examples

jobs:
  # Every minute
  - name: "Heartbeat"
    minute: "*"
    hour: "*"
    weekday: "*"
    command: "echo 'alive'"

  # Every 5 minutes
  - name: "Frequent Check"
    minute: "*/5"
    hour: "*"
    weekday: "*"
    command: "check-service.sh"

  # At specific minutes
  - name: "Quarter Hours"
    minute: "0,15,30,45"
    hour: "*"
    weekday: "*"
    command: "quarter-hour-task.sh"

  # Business hours only (9 AM - 5 PM)
  - name: "Business Task"
    minute: "0"
    hour: "9-17"
    weekday: "*"
    command: "business-process.sh"

  # Complex schedule
  - name: "Complex Task"
    minute: "5-55/10"  # At 5, 15, 25, 35, 45, 55
    hour: "8-18/2"     # Every 2 hours from 8 AM to 6 PM
    weekday: "*"
    command: "complex-task.sh"

Weekday Field Example

jobs:
  - name: "Weekday Task"
    minute: "0"
    hour: "9"
    weekday: "1-5"  # Monday to Friday
    command: "weekday-task.sh"

Notification Configuration

Gotify Configuration

notification:
  - name: gotify-alerts
    success:
      gotify:
        url: "https://gotify.example.com/message?token=YOUR_TOKEN"
    error:
      gotify:
        url: "https://gotify.example.com/message?token=YOUR_PRIORITY_TOKEN"

Gotify notifications include:

  • Success messages with low priority (-1)
  • Error messages with high priority (10)
  • Job name, command, and output in the message body

SMTP Configuration

notification:
  - name: email-alerts
    success:
      smtp:
        host: "smtp.office365.com"
        port: 587
        username: "notifications@company.com"
        password: "secure-password"
        from: "scron@company.com"
        to: "devops@company.com"
        use_ssl: true
    error:
      smtp:
        host: "smtp.office365.com"
        port: 587
        username: "alerts@company.com"
        password: "secure-password"
        from: "scron-alerts@company.com"
        to: "oncall@company.com"
        use_ssl: true

Multiple Notification Channels

You can configure both Gotify and SMTP in the same notification configuration - both will be used:

notification:
  - name: multi-channel
    error:
      gotify:
        url: "https://gotify.example.com/message?token=TOKEN"
      smtp:
        host: "smtp.gmail.com"
        port: 587
        username: "alerts@example.com"
        password: "app-password"
        from: "scron@example.com"
        to: "team@example.com"
        use_ssl: true

Advanced Examples

Database Maintenance

jobs:
  - name: "PostgreSQL Vacuum"
    minute: "0"
    hour: "4"
    command: "psql -U postgres -d mydb -c 'VACUUM ANALYZE;'"
    notification: database-alerts

  - name: "MySQL Backup"
    minute: "30"
    hour: "3"
    command: |
      mysqldump --all-databases > /backup/mysql_$(date +%Y%m%d_%H%M%S).sql && \
      find /backup -name "mysql_*.sql" -mtime +7 -delete
    notification: backup-alerts

System Monitoring

jobs:
  - name: "Disk Space Check"
    minute: "*/30"
    hour: "*"
    command: |
      USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
      if [ $USAGE -gt 80 ]; then
        echo "WARNING: Disk usage is at ${USAGE}%"
        exit 1
      fi
    notification: critical-alerts

  - name: "Memory Check"
    minute: "*/10"
    hour: "*"
    command: |
      FREE_MEM=$(free -m | awk 'NR==2 {print $4}')
      if [ $FREE_MEM -lt 500 ]; then
        echo "Low memory: ${FREE_MEM}MB free"
        exit 1
      fi
    notification: system-alerts

Log Rotation

jobs:
  - name: "Rotate Application Logs"
    minute: "0"
    hour: "0"
    command: |
      find /var/log/myapp -name "*.log" -size +100M -exec gzip {} \; && \
      find /var/log/myapp -name "*.gz" -mtime +30 -delete

Logging

SCRON uses structured JSON logging with zerolog. Logs include:

  • Job execution start/completion
  • Command output (stdout and stderr)
  • Exit codes
  • Execution errors
  • Configuration reload events
  • Notification delivery status

Example log output:

{"level":"info","time":"2024-01-15T10:00:00Z","message":"Executing job","job":"Database Backup","command":"pg_dump mydb > backup.sql"}
{"level":"info","time":"2024-01-15T10:00:05Z","message":"Job completed","job":"Database Backup","exit_code":0}

Error Handling

SCRON provides comprehensive error handling:

  • Configuration Errors: Invalid YAML, missing required fields
  • Time Pattern Errors: Invalid cron patterns with detailed error messages
  • Execution Errors: Command failures, non-zero exit codes
  • Notification Errors: Failed delivery attempts are logged but don't stop job execution

Best Practices

  1. Use Absolute Paths: Always use absolute paths in commands to avoid PATH issues
  2. Set Proper Exit Codes: Ensure your scripts exit with non-zero codes on failure
  3. Test Commands: Test your commands manually before adding to configuration
  4. Monitor Logs: Regularly check SCRON logs for execution issues
  5. Use Notifications Wisely: Configure different notification channels for different severity levels
  6. Keep Commands Simple: For complex tasks, use shell scripts instead of inline commands