restic-scheduler/shell.go

75 lines
1.5 KiB
Go

package main
import (
"fmt"
"log"
"os"
"os/exec"
"strings"
)
var (
loggerFlags = log.LstdFlags | log.Lmsgprefix
loggers = map[string]*log.Logger{}
)
func GetLogger(name string) *log.Logger {
if logger, ok := loggers[name]; ok {
return logger
}
logger := log.New(os.Stderr, name+":", loggerFlags)
loggers[name] = logger
return logger
}
func GetChildLogger(parent *log.Logger, name string) *log.Logger {
childName := fmt.Sprintf("%s%s", parent.Prefix(), name)
return GetLogger(childName)
}
type CapturedLogWriter struct {
Lines []string
logger *log.Logger
}
func NewCapturedLogWriter(logger *log.Logger) *CapturedLogWriter {
return &CapturedLogWriter{Lines: []string{}, logger: logger}
}
func (w *CapturedLogWriter) Write(content []byte) (n int, err error) {
message := string(content)
for _, line := range strings.Split(message, "\n") {
w.Lines = append(w.Lines, line)
w.logger.Printf(" %s", line)
}
return len(content), nil
}
func RunShell(script string, cwd string, env map[string]string, logger *log.Logger) error {
cmd := exec.Command("sh", "-c", strings.TrimSpace(script)) // nolint:gosec
// Make both stderr and stdout go to logger
cmd.Stdout = NewCapturedLogWriter(logger)
cmd.Stderr = cmd.Stdout
// Set working directory
cmd.Dir = cwd
// Convert env to list if values provided
if len(env) > 0 {
envList := os.Environ()
envList = append(envList, EnvMapToList(env)...)
cmd.Env = envList
}
if err := cmd.Run(); err != nil {
return fmt.Errorf("shell execution failed: %w", err)
}
return nil
}