@@ -5,8 +5,10 @@ import (
55 "log"
66 "os"
77 "os/exec"
8+ "os/signal"
89 "strconv"
910 "strings"
11+ "syscall"
1012 "time"
1113)
1214
@@ -264,12 +266,21 @@ var defaultCommandRunner CommandRunner = &RealCommandRunner{}
264266func executeCommand (command string ) {
265267 log .Printf ("Running command: %s" , command )
266268
269+ // Check if bash exists, fallback to sh if not
270+ shell := "/bin/bash"
271+ if _ , err := os .Stat (shell ); os .IsNotExist (err ) {
272+ shell = "/bin/sh"
273+ log .Printf ("Bash not found, using sh instead" )
274+ }
275+
267276 // u0438u0441u043fu043eu043bu044cu0437u0443u0435u043c u0438u043du0442u0435u0440u0444u0435u0439u0441 CommandRunner u0434u043bu044f u0432u043eu0437u043cu043eu0436u043du043eu0441u0442u0438 u043cu043eu043au0438u0440u043eu0432u0430u043du0438u044f
268- output , err := defaultCommandRunner .Run ("/bin/bash" , "-c" , command )
277+ output , err := defaultCommandRunner .Run (shell , "-c" , command )
269278
270279 if err != nil {
271280 log .Printf ("Error executing command %s: %v" , command , err )
281+ // Don't exit, just log the error and continue
272282 }
283+
273284 log .Printf ("Output from command %s: %s" , command , string (output ))
274285}
275286
@@ -285,10 +296,18 @@ func createEveryTickers(tasks []*CronSchedule) []*time.Ticker {
285296
286297 for _ , task := range tasks {
287298 if task .isEvery {
299+ log .Printf ("Setting up @every ticker for task '%s' with interval %v" , task .command , task .interval )
288300 ticker := time .NewTicker (task .interval )
289301 tickers = append (tickers , ticker )
290302
291303 go func (t * CronSchedule , tkr * time.Ticker ) {
304+ // Recover from panics
305+ defer func () {
306+ if r := recover (); r != nil {
307+ log .Printf ("Recovered from panic in @every ticker for '%s': %v" , t .command , r )
308+ }
309+ }()
310+
292311 for range tkr .C {
293312 go executeCommand (t .command )
294313 }
@@ -321,13 +340,24 @@ func startCronScheduler(tasks []*CronSchedule) {
321340 }
322341 }()
323342
343+ // Recover from panics
344+ defer func () {
345+ if r := recover (); r != nil {
346+ log .Printf ("Recovered from panic in scheduler: %v" , r )
347+ }
348+ }()
349+
324350 // Main ticker for regular cron jobs
325351 ticker := time .NewTicker (time .Minute )
326352 defer ticker .Stop ()
327353
354+ // Log initial startup
355+ log .Printf ("Scheduler started with %d tasks" , len (tasks ))
356+
328357 for {
329358 select {
330359 case t := <- ticker .C :
360+ log .Printf ("Running cron tasks at %s" , t .Format (time .RFC3339 ))
331361 runCronTasks (tasks , t )
332362 }
333363 }
@@ -336,6 +366,24 @@ func startCronScheduler(tasks []*CronSchedule) {
336366// main initializes and runs the cron scheduler.
337367// Creates separate tickers for @every tasks and a main ticker for standard cron tasks.
338368func main () {
369+ // Setup signal handling for graceful shutdown
370+ sigChan := make (chan os.Signal , 1 )
371+ signal .Notify (sigChan , os .Interrupt , syscall .SIGTERM )
372+
339373 tasks := loadTasks ()
340- startCronScheduler (tasks )
374+
375+ // Start scheduler in a goroutine
376+ done := make (chan bool )
377+ go func () {
378+ startCronScheduler (tasks )
379+ done <- true
380+ }()
381+
382+ // Wait for either a signal or scheduler completion
383+ select {
384+ case sig := <- sigChan :
385+ log .Printf ("Received signal %v, shutting down..." , sig )
386+ case <- done :
387+ log .Printf ("Scheduler completed unexpectedly" )
388+ }
341389}
0 commit comments