Hallucinate a basic cronjob interface

This commit is contained in:
2025-06-27 18:13:18 +02:00
parent 6680ef4243
commit 8eb816da9b
3 changed files with 88 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ go 1.23.6
require (
git.site.quack-lab.dev/dave/cylogger v1.2.3
github.com/fsnotify/fsnotify v1.9.0
github.com/robfig/cron/v3 v3.0.1
)
require golang.org/x/sys v0.13.0 // indirect

View File

@@ -2,5 +2,7 @@ git.site.quack-lab.dev/dave/cylogger v1.2.3 h1:g6fwgrd3HvGsxljvKbjcFaMynTO2AZFWj
git.site.quack-lab.dev/dave/cylogger v1.2.3/go.mod h1:sf16Zs5ZRncn0ySgwxRJShkge1M10CM2RAUkKn8Bel8=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@@ -4,9 +4,12 @@ import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/fsnotify/fsnotify"
"github.com/robfig/cron/v3"
logger "git.site.quack-lab.dev/dave/cylogger"
)
@@ -17,6 +20,7 @@ type CronJob struct {
}
var crontabFile string
var cronRunner *cron.Cron
func main() {
flag.Parse()
@@ -36,6 +40,20 @@ func main() {
}
logger.Info("Crontab file resolved as: %s", crontabFile)
// Initialize cron runner with seconds disabled (standard cron format)
cronRunner = cron.New()
defer cronRunner.Stop()
// Load initial cron jobs
if err := loadCronJobs(); err != nil {
logger.Error("Failed to load initial cron jobs: %v", err)
return
}
// Start the cron scheduler
cronRunner.Start()
logger.Info("Cron scheduler started")
events, err := watchCrontabFile(crontabFile)
if err != nil {
logger.Error("Failed to watch crontab file: %v", err)
@@ -43,6 +61,73 @@ func main() {
}
for event := range events {
logger.Info("Crontab file updated: %s", event.Name)
// Reload cron jobs when file changes
if err := loadCronJobs(); err != nil {
logger.Error("Failed to reload cron jobs: %v", err)
}
}
}
func loadCronJobs() error {
// Read the crontab file
content, err := os.ReadFile(crontabFile)
if err != nil {
return fmt.Errorf("failed to read crontab file: %v", err)
}
// Stop current jobs
cronRunner.Stop()
// Create new cron runner
cronRunner = cron.New()
// Parse each line
lines := strings.Split(string(content), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
// Split into cron expression and command
fields := strings.Fields(line)
if len(fields) < 6 {
logger.Error("Invalid cron line: %s", line)
continue
}
cronExpr := strings.Join(fields[0:5], " ")
cmdStr := strings.Join(fields[5:], " ")
job := CronJob{
Cron: cronExpr,
Command: cmdStr,
}
// Add the job to cron
_, err := cronRunner.AddFunc(job.Cron, createJobFunc(job))
if err != nil {
logger.Error("Failed to add cron job %+v: %v", job, err)
continue
}
logger.Info("Added cron job: %s -> %s", job.Cron, job.Command)
}
// Start the cron scheduler
cronRunner.Start()
return nil
}
func createJobFunc(job CronJob) func() {
return func() {
cmd := exec.Command("sh", "-c", job.Command)
output, err := cmd.CombinedOutput()
if err != nil {
logger.Error("Failed to execute command '%s': %v", job.Command, err)
logger.Error("Command output: %s", string(output))
return
}
logger.Info("Successfully executed command '%s'", job.Command)
logger.Info("Command output: %s", string(output))
}
}