diff --git a/README.md b/README.md index 84f3814..778eb15 100644 --- a/README.md +++ b/README.md @@ -1,149 +1,319 @@ # SCRON -A lightweight, efficient cron-like scheduler written in Go that executes shell commands at specified intervals with precise timing and comprehensive logging. +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**: Schedule jobs using minute and hour patterns with wildcard support -- **Configuration Reloading**: Monitors config file changes for dynamic job updates -- **Comprehensive Logging**: Detailed execution logs using `zerolog` with configurable levels -- **Error Handling**: Robust error handling with exit code tracking and output capture -- **Shell Command Support**: Execute any shell command via bash -- **Notifications**: Send job status notifications via Gotify and SMTP +- **🕐 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 -### Recommended: Debian Package (.deb) +### From Source -Download the latest `.deb` package from the [releases page](https://git.keks.cloud/kekskurse/scron/releases) and install: +```bash +# 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](https://git.keks.cloud/kekskurse/scron/releases): + +```bash # Install package sudo dpkg -i scron_X.X.X_linux_amd64.deb +``` -Configuration file at `/etc/scron/config.yml` +Configuration file location: `/etc/scron/config.yml` ## Configuration -Create a `config.yml` file in the same directory as the binary (or /etc/scron if install via .deb): +Create a `config.yml` file in the same directory as the binary (or `/etc/scron/` for package installations): + +### Basic Configuration ```yaml jobs: + - name: "System Health Check" + minute: "*/5" + hour: "*" + command: "curl -f http://localhost:8080/health || exit 1" + - name: "Daily Backup" minute: "0" hour: "2" - command: "backup.sh /data /backup" - - - name: "Health Check" - minute: "*/5" - hour: "*" - command: "curl -f http://localhost:8080/health" - - - name: "Log Cleanup" - minute: "30" - hour: "1" - command: "find /var/log -name '*.log' -mtime +7 -delete" + command: "/usr/local/bin/backup.sh" ``` -### Configuration Fields - -| Field | Description | Format | Examples | -|-------|-------------|--------|----------| -| `name` | Descriptive job name for logging | String | "Daily Backup", "Health Check" | -| `minute` | Minute pattern (0-59) | String | `"0"`, `"*/5"`, `"15,30,45"`, `"*"` | -| `hour` | Hour pattern (0-23) | String | `"2"`, `"*/2"`, `"9-17"`, `"*"` | -| `command` | Shell command to execute | String | `"echo 'Hello'"`, `"backup.sh"` | -| `notification` | Name of notification configuration to use | String | `"default"` | - -### Notifications - -You can configure notifications for job success or failure using Gotify and SMTP: +### Advanced Configuration with Notifications ```yaml +# Notification configurations notification: - name: default success: - gotify: - url: https://gotify.example.com/message?token=YOUR_TOKEN + gotify: + url: "https://gotify.example.com/message?token=YOUR_TOKEN" smtp: - host: smtp.example.com - port: "587" - username: your_username - password: your_password - from: sender@example.com - to: recipient@example.com + 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_TOKEN + url: "https://gotify.example.com/message?token=YOUR_CRITICAL_TOKEN" smtp: - host: smtp.example.com - port: "587" - username: your_username - password: your_password - from: sender@example.com - to: recipient@example.com + 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: "Daily Backup" + - name: "Database Backup" minute: "0" - hour: "2" - command: "backup.sh /data /backup" + hour: "3" + command: "pg_dump mydb > /backup/mydb_$(date +%Y%m%d).sql" notification: default + + - name: "Critical Service Monitor" + minute: "*/1" + hour: "*" + command: "systemctl is-active nginx || exit 1" + notification: critical-only ``` -Notifications support: -- Multiple named notification configurations -- Separate success and error notification URLs -- Optional configuration per job -- Gotify and SMTP notification methods -- Multiple recipients for SMTP -- TLS support for SMTP +## Time Pattern Syntax -### Pattern Syntax -- `*` - Every minute/hour -- `*/n` - Every n minutes/hours -- `n` - Specific minute/hour -- `n,m,o` - Multiple specific values -- `n-m` - Range of values +SCRON supports flexible cron-like time patterns for both minutes (0-59) and hours (0-23): +| 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 | -## Examples +### Pattern Examples -### Simple Periodic Task ```yaml jobs: + # Every minute - name: "Heartbeat" minute: "*" hour: "*" - command: "echo $(date): Service running >> /var/log/heartbeat.log" -``` + command: "echo 'alive'" -### Business Hours Only -```yaml -jobs: - - name: "Business Hours Check" + # Every 5 minutes + - name: "Frequent Check" + minute: "*/5" + hour: "*" + command: "check-service.sh" + + # At specific minutes + - name: "Quarter Hours" + minute: "0,15,30,45" + hour: "*" + command: "quarter-hour-task.sh" + + # Business hours only (9 AM - 5 PM) + - name: "Business Task" minute: "0" hour: "9-17" - command: "business-hours-task.sh" + 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 + command: "complex-task.sh" ``` -### Multiple Schedules +## Notification Configuration + +### Gotify Configuration + +```yaml +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 + +```yaml +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: + +```yaml +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 + ```yaml jobs: - - name: "Frequent Check" - minute: "*/2" - hour: "*" - command: "quick-check.sh" - - - name: "Hourly Report" - minute: "0" - hour: "*" - command: "generate-report.sh" - - - name: "Daily Cleanup" + - 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: "cleanup.sh" + 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 + +```yaml +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 + +```yaml +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: +```json +{"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 +