This commit is contained in:
parent
643281dfb3
commit
14cc0a7d6a
1 changed files with 258 additions and 88 deletions
342
README.md
342
README.md
|
|
@ -1,149 +1,319 @@
|
||||||
# SCRON
|
# 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
|
## Features
|
||||||
|
|
||||||
- **Flexible Scheduling**: Schedule jobs using minute and hour patterns with wildcard support
|
- **🕐 Flexible Scheduling**: Advanced cron-like time patterns with minute-level precision
|
||||||
- **Configuration Reloading**: Monitors config file changes for dynamic job updates
|
- **🔄 Dynamic Configuration**: Automatic config reloading without restart
|
||||||
- **Comprehensive Logging**: Detailed execution logs using `zerolog` with configurable levels
|
- **📊 Structured Logging**: JSON-formatted logs with zerolog for easy parsing
|
||||||
- **Error Handling**: Robust error handling with exit code tracking and output capture
|
- **🔔 Multi-Channel Notifications**: Support for Gotify and SMTP notifications
|
||||||
- **Shell Command Support**: Execute any shell command via bash
|
- **⚡ Concurrent Execution**: Jobs run in parallel for optimal performance
|
||||||
- **Notifications**: Send job status notifications via Gotify and SMTP
|
- **🛡️ Robust Error Handling**: Comprehensive error tracking with exit codes
|
||||||
|
- **📝 Output Capture**: Combined stdout/stderr capture for debugging
|
||||||
|
|
||||||
## Installation
|
## 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
|
# Install package
|
||||||
sudo dpkg -i scron_X.X.X_linux_amd64.deb
|
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
|
## 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
|
```yaml
|
||||||
jobs:
|
jobs:
|
||||||
|
- name: "System Health Check"
|
||||||
|
minute: "*/5"
|
||||||
|
hour: "*"
|
||||||
|
command: "curl -f http://localhost:8080/health || exit 1"
|
||||||
|
|
||||||
- name: "Daily Backup"
|
- name: "Daily Backup"
|
||||||
minute: "0"
|
minute: "0"
|
||||||
hour: "2"
|
hour: "2"
|
||||||
command: "backup.sh /data /backup"
|
command: "/usr/local/bin/backup.sh"
|
||||||
|
|
||||||
- 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"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuration Fields
|
### Advanced Configuration with Notifications
|
||||||
|
|
||||||
| 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:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
# Notification configurations
|
||||||
notification:
|
notification:
|
||||||
- name: default
|
- name: default
|
||||||
success:
|
success:
|
||||||
gotify:
|
gotify:
|
||||||
url: https://gotify.example.com/message?token=YOUR_TOKEN
|
url: "https://gotify.example.com/message?token=YOUR_TOKEN"
|
||||||
smtp:
|
smtp:
|
||||||
host: smtp.example.com
|
host: "smtp.gmail.com"
|
||||||
port: "587"
|
port: 587
|
||||||
username: your_username
|
username: "your-email@gmail.com"
|
||||||
password: your_password
|
password: "your-app-password"
|
||||||
from: sender@example.com
|
from: "scron@example.com"
|
||||||
to: recipient@example.com
|
to: "admin@example.com"
|
||||||
use_ssl: true
|
use_ssl: true
|
||||||
error:
|
error:
|
||||||
gotify:
|
gotify:
|
||||||
url: https://gotify.example.com/message?token=YOUR_TOKEN
|
url: "https://gotify.example.com/message?token=YOUR_CRITICAL_TOKEN"
|
||||||
smtp:
|
smtp:
|
||||||
host: smtp.example.com
|
host: "smtp.gmail.com"
|
||||||
port: "587"
|
port: 587
|
||||||
username: your_username
|
username: "your-email@gmail.com"
|
||||||
password: your_password
|
password: "your-app-password"
|
||||||
from: sender@example.com
|
from: "scron-alerts@example.com"
|
||||||
to: recipient@example.com
|
to: "oncall@example.com"
|
||||||
use_ssl: true
|
use_ssl: true
|
||||||
|
|
||||||
|
- name: critical-only
|
||||||
|
error:
|
||||||
|
gotify:
|
||||||
|
url: "https://gotify.example.com/message?token=YOUR_CRITICAL_TOKEN"
|
||||||
|
|
||||||
|
# Job definitions
|
||||||
jobs:
|
jobs:
|
||||||
- name: "Daily Backup"
|
- name: "Database Backup"
|
||||||
minute: "0"
|
minute: "0"
|
||||||
hour: "2"
|
hour: "3"
|
||||||
command: "backup.sh /data /backup"
|
command: "pg_dump mydb > /backup/mydb_$(date +%Y%m%d).sql"
|
||||||
notification: default
|
notification: default
|
||||||
|
|
||||||
|
- name: "Critical Service Monitor"
|
||||||
|
minute: "*/1"
|
||||||
|
hour: "*"
|
||||||
|
command: "systemctl is-active nginx || exit 1"
|
||||||
|
notification: critical-only
|
||||||
```
|
```
|
||||||
|
|
||||||
Notifications support:
|
## Time Pattern Syntax
|
||||||
- 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
|
|
||||||
|
|
||||||
### Pattern Syntax
|
SCRON supports flexible cron-like time patterns for both minutes (0-59) and hours (0-23):
|
||||||
- `*` - Every minute/hour
|
|
||||||
- `*/n` - Every n minutes/hours
|
|
||||||
- `n` - Specific minute/hour
|
|
||||||
- `n,m,o` - Multiple specific values
|
|
||||||
- `n-m` - Range of values
|
|
||||||
|
|
||||||
|
| 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
|
```yaml
|
||||||
jobs:
|
jobs:
|
||||||
|
# Every minute
|
||||||
- name: "Heartbeat"
|
- name: "Heartbeat"
|
||||||
minute: "*"
|
minute: "*"
|
||||||
hour: "*"
|
hour: "*"
|
||||||
command: "echo $(date): Service running >> /var/log/heartbeat.log"
|
command: "echo 'alive'"
|
||||||
```
|
|
||||||
|
|
||||||
### Business Hours Only
|
# Every 5 minutes
|
||||||
```yaml
|
- name: "Frequent Check"
|
||||||
jobs:
|
minute: "*/5"
|
||||||
- name: "Business Hours Check"
|
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"
|
minute: "0"
|
||||||
hour: "9-17"
|
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
|
```yaml
|
||||||
jobs:
|
jobs:
|
||||||
- name: "Frequent Check"
|
- name: "PostgreSQL Vacuum"
|
||||||
minute: "*/2"
|
|
||||||
hour: "*"
|
|
||||||
command: "quick-check.sh"
|
|
||||||
|
|
||||||
- name: "Hourly Report"
|
|
||||||
minute: "0"
|
minute: "0"
|
||||||
hour: "*"
|
hour: "4"
|
||||||
command: "generate-report.sh"
|
command: "psql -U postgres -d mydb -c 'VACUUM ANALYZE;'"
|
||||||
|
notification: database-alerts
|
||||||
|
|
||||||
- name: "Daily Cleanup"
|
- name: "MySQL Backup"
|
||||||
minute: "0"
|
minute: "30"
|
||||||
hour: "3"
|
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
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue