123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- package main
-
- import (
- "context"
- "io"
- "io/ioutil"
- "log"
- "os"
- "os/exec"
- "reflect"
- "syscall"
- "time"
-
- "github.com/kr/pty" // required to run commands as other users
- )
-
- // readTasksDirectory get contents of target directory
- func readTasksDirectory(path string) []string {
- var res []string
-
- files, err := ioutil.ReadDir(path)
- if err != nil {
- log.Fatal(err)
- }
-
- for _, file := range files {
- //log.Println(file.Name())
- res = append(res, path+"/"+file.Name())
- }
-
- return res
- }
-
- func inArray(val interface{}, array interface{}) (exists bool, index int) {
- exists = false
- index = -1
-
- switch reflect.TypeOf(array).Kind() {
- case reflect.Slice:
- s := reflect.ValueOf(array)
-
- for i := 0; i < s.Len(); i++ {
- if reflect.DeepEqual(val, s.Index(i).Interface()) == true {
- index = i
- exists = true
- return
- }
- }
- }
-
- return
- }
-
- // 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...)
-
- // set env variables
- cmd.Env = append(cmd.Env, os.Environ()...)
- cmd.Env = append(cmd.Env, env...)
-
- // run su command in PTY
- f, err := pty.Start(cmd)
- if err != nil {
- panic(err)
- }
-
- // set stdout, stderr
- if v, _ := inArray("LOGTYPE=full", env); v == true {
- io.Copy(os.Stdout, f)
- io.Copy(os.Stderr, f)
- }
-
- // Use a channel to signal completion so we can use a select statement
- done := make(chan error)
- go func() { done <- cmd.Wait() }()
-
- // The select statement allows us to execute based on which channel
- // we get a message from first.
- select {
- case <-ctx.Done():
- // Timeout happened first, kill the process and print a message.
- cmd.Process.Signal(syscall.SIGTERM)
- // gracefulStopSeconds is a time between SIGTERM and SIGKILL, default 10s, minimum 1s
- time.AfterFunc(gracefulStopSeconds, func() {
- if !cmd.ProcessState.Exited() {
- cmd.Process.Kill()
- }
- })
- return ctx.Err()
- case err := <-done:
- return err
- }
-
- return nil
- }
|