package main import ( "bytes" "os/exec" "syscall" "time" "github.com/rs/zerolog" "github.com/rs/zerolog/log" ) var currentConfig config func main() { zerolog.SetGlobalLevel(zerolog.InfoLevel) log.Info().Msg("Start") var err error currentConfig, err = ReadFromFile("config.yml") if err != nil { log.Fatal().Err(err).Msg("Cant read config file") } log.Debug().Interface("config", currentConfig).Msg("config") if len(currentConfig.Jobs) == 0 { log.Warn().Msg("config dont include any jobs") } cronTicker, configTicker := createTickers(realTimeProvider{}) // Hauptloop mit select for { select { case t := <-cronTicker: execucteJobs(t, currentConfig) case <-configTicker: log.Debug().Msg("Reload Config") currentConfig, err = ReadFromFile("config.yml") if err != nil { log.Error().Err(err).Msg("cant read config") } } } } func execucteJobs(t time.Time, c config) { for _, job := range c.Jobs { execute, err := job.MatchCurrentTime(t) log.Debug().Bool("execution", execute).Time("t", t).Msg("check cron execution") if err != nil { log.Error().Err(err).Msg("cant pars time for job") } if !execute { continue } go executeJob(t, job, c) } } func executeJob(t time.Time, job jobconfig, c config) { result, err := executeCommand(job) log.Info().Str("name", job.Name).Str("command", job.Command).Time("execute-for", t).Int("execCode", result.execCode).Str("output", result.outputString).Err(result.err).Msg("Done execute task") if err != nil { log.Err(err).Msg("Error while Execute command") } nc := notificationConfig{} for _, n := range c.Notification { if n.Name == job.Notification { nc = n } } sendNotification(result, nc) } func sendNotification(result jobResult, notification notificationConfig) error { title := "" msg := Message{} msg.Priority = 10 if result.isSuccess() { title = "✅ [scron] " + result.job.Name msg.Priority = -1 } else { title = "❌ [scron] " + result.job.Name } msg.Message = result.outputString msg.Title = title if result.isSuccess() { if notification.Success.Gotify.URL != "" { err := SendGotifyNotification(notification.Success.Gotify.URL, msg) if err != nil { log.Error().Err(err).Msg("cant send gotify notification") } } if notification.Success.Smtp.Host != "" { err := SendSMTPNotification(notification.Success.Smtp, title, result.outputString) if err != nil { log.Error().Err(err).Msg("cant send smtp notification") } } } else { if notification.Error.Gotify.URL != "" { err := SendGotifyNotification(notification.Error.Gotify.URL, msg) if err != nil { log.Error().Err(err).Msg("cant send gotify notification") } } if notification.Error.Smtp.Host != "" { err := SendSMTPNotification(notification.Error.Smtp, title, result.outputString) if err != nil { log.Error().Err(err).Msg("cant send smtp notification") } } } return nil } func executeCommand(job jobconfig) (jobResult, error) { j := jobResult{} j.job = job var output bytes.Buffer cmd := exec.Command("bash", "-c", job.Command) cmd.Stdout = &output cmd.Stderr = &output err := cmd.Run() j.outputString = output.String() if err != nil { if exitErr, ok := err.(*exec.ExitError); ok { if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { j.execCode = status.ExitStatus() } } else { j.err = err return j, err } } return j, nil }