Bläddra i källkod

added gracefulstop period

tags/version-1.1.1
Vladimir Smagin 7 månader sedan
förälder
incheckning
c3f3e72f52
7 ändrade filer med 64 tillägg och 31 borttagningar
  1. 1
    1
      build.sh
  2. 4
    2
      config.go
  3. 1
    0
      configs/test1.yml
  4. 1
    1
      debian/DEBIAN/control
  5. 16
    3
      file_utils.go
  6. 21
    15
      gogocron.go
  7. 20
    9
      readme.md

+ 1
- 1
build.sh Visa fil

@@ -1,6 +1,6 @@
#!/bin/bash

VERSION="1.1"
VERSION="1.1.1"

# build gogocron
go build

+ 4
- 2
config.go Visa fil

@@ -53,13 +53,15 @@ func readTaskConfigFile(path string) cronTask {
log.Fatalf("Error opening file %v", err)
}

//log.Printf(string(yamldata))

marshErr := yaml.Unmarshal(yamldata, &config)
if marshErr != nil {
log.Fatalf("Task file malformed: %v", marshErr)
}

if config.GracefulStop == "" {
config.GracefulStop = "10s"
}

return config
}


+ 1
- 0
configs/test1.yml Visa fil

@@ -3,6 +3,7 @@ name: "TASK #1"
runsecond: "*/5"
logtype: full
user: vlad
gracefulstop: 30s
env:
- TESTVAR="test variable"
commands:

+ 1
- 1
debian/DEBIAN/control Visa fil

@@ -1,5 +1,5 @@
Package: gogocron
Version: 1.1
Version: 1.1.1
Section: base
Priority: optional
Installed-Size: 3 MB

+ 16
- 3
file_utils.go Visa fil

@@ -53,6 +53,20 @@ func inArray(val interface{}, array interface{}) (exists bool, index int) {

// run commands
func runCmd(ctx context.Context, env []string, cmdname string, params ...string) error {

// Read graceful stop value from context
var gracefulStop string
if v := ctx.Value("gracefulstopvalue"); v != nil {
gracefulStop = v.(string)
} else {
gracefulStop = "10s"
}

gracefulStopSeconds, err := time.ParseDuration(gracefulStop)
if err != nil {
log.Fatalln("Error parsing gracefulstop value as time duration")
}

//log.Println("Executing", cmdname, params)
cmd := exec.Command(cmdname, params...)

@@ -82,9 +96,8 @@ func runCmd(ctx context.Context, env []string, cmdname string, params ...string)
case <-ctx.Done():
// Timeout happened first, kill the process and print a message.
cmd.Process.Signal(syscall.SIGTERM)
// graceful stop 10 seconds
// if task must be killed instead of normal termination
time.AfterFunc(10*time.Second, func() {
// gracefulStopSeconds is a time between SIGTERM and SIGKILL, default 10s, minimum 1s
time.AfterFunc(gracefulStopSeconds, func() {
if !cmd.ProcessState.Exited() {
cmd.Process.Kill()
}

+ 21
- 15
gogocron.go Visa fil

@@ -31,18 +31,19 @@ type cronConfig struct {
}

type cronTask struct {
Name string `yaml:"name"` // name of task
AsUser string `yaml:"user,omitempty"` // run as user
RunSecond string `yaml:"runsecond,omitempty"` // second
RunMinute string `yaml:"runminute,omitempty"` // minute
RunHour string `yaml:"runhour,omitempty"` // hour
RunDom string `yaml:"rundom,omitempty"` // day of month
RunMonth string `yaml:"runmonth,omitempty"` // month
RunDow string `yaml:"rundow,omitempty"` // day of week
TimeOut string `yaml:"timeout,omitempty"` // exec with timeout, seconds
Env []string `yaml:"env,omitempty"` // array of env variables
Commands []string `yaml:"commands"` // array of commands to exec
LogType string `yaml:"logtype,omitempty"` // type of logging: info, full, disabled
Name string `yaml:"name"` // name of task
AsUser string `yaml:"user,omitempty"` // run as user
RunSecond string `yaml:"runsecond,omitempty"` // second
RunMinute string `yaml:"runminute,omitempty"` // minute
RunHour string `yaml:"runhour,omitempty"` // hour
RunDom string `yaml:"rundom,omitempty"` // day of month
RunMonth string `yaml:"runmonth,omitempty"` // month
RunDow string `yaml:"rundow,omitempty"` // day of week
TimeOut string `yaml:"timeout,omitempty"` // exec with timeout, seconds
Env []string `yaml:"env,omitempty"` // array of env variables
Commands []string `yaml:"commands"` // array of commands to exec
LogType string `yaml:"logtype,omitempty"` // type of logging: info, full, disabled
GracefulStop string `yaml:"gracefulstop,omitempty"` // seconds between task term and kill
}

type cronTasks []cronTask
@@ -133,6 +134,11 @@ func executeTask(ctx context.Context, task cronTask) {
// flag to stop timed out tasks
timeoutFlag := false

// send gracefulstop with context
type contextKey string
gracefulStop := contextKey("gracefulstopvalue")
ctxRunCmd := context.WithValue(ctx, gracefulStop, task.GracefulStop)

// iterate commands list
for _, cmd := range task.Commands {
if timeoutFlag {
@@ -140,19 +146,19 @@ func executeTask(ctx context.Context, task cronTask) {
}

select {
case <-ctx.Done():
case <-ctxRunCmd.Done():
log.Printf("Timeout exceeded for task %v", task.Name)
timeoutFlag = true
default:
// su required to run as other users, requires pty to run
runCmd(ctx, task.Env, "su", "-c", cmd, task.AsUser)
runCmd(ctxRunCmd, task.Env, "su", "-c", cmd, task.AsUser)
}
}

}

func main() {
log.Println("gogocron 1.1 by Vladimir Smagin (http://gogocron.blindage.org)")
log.Println("gogocron 1.1.1 by Vladimir Smagin (http://gogocron.blindage.org)")

// Load config at startup, once
gogoConfig := loadConfig()

+ 20
- 9
readme.md Visa fil

@@ -13,12 +13,7 @@ Cron daemon with crontab syntax, small interval and execution timeout for each t
- run task commands as other user
- timeout for whole task with default graceful period 10s
- SIGHUP process to reload config files

### Planned

- *1.1.1*: Adjustable graceful timeout period for each task, current default is 10s.

By default if task not die after SIGTERM in 10s cron send SIGKILL signal. In future you can adjust this value for each task.
- adjustable graceful timeout period for each command in task

## Installation

@@ -105,16 +100,32 @@ rundow // day of week

#### Timeout

Golang's time.Duration definition, string.
If whole task (not one command in task) running more than timeout cron send SIGTERM signal, by default timeout is turned off.

```
timeout: 3h12m4s
```

It's a golang's [time.Duration](https://golang.org/pkg/time/#Duration) definition, string:

- 1s - one second
- 1m10s - one minute and 10 seconds


#### Graceful stop

By default if task's command not die after SIGTERM in 10s cron send SIGKILL signal. You may need this if your program receiving signals but internal queue not empty for immidiately stop.

You can change this time with:

```
timeout: 3h12m4s
gracefulstop: 30s
```

By default if task not die after SIGTERM in 10s cron send SIGKILL signal.
It's a golang's [time.Duration](https://golang.org/pkg/time/#Duration) definition, string:

- 1s - one second
- 1m10s - one minute and 10 seconds

#### ENV


Laddar…
Avbryt
Spara