From 0dd4771d9c6cffa92b1c82cf6fa633620c049d0e Mon Sep 17 00:00:00 2001 From: Daniel Theophanes Date: Sat, 28 Mar 2015 23:31:00 -0700 Subject: [PATCH] service/example: add exec runner. --- example/runner/runner.go | 170 +++++++++++++++++++++++++++++++++++++ example/runner/runner.json | 15 ++++ 2 files changed, 185 insertions(+) create mode 100644 example/runner/runner.go create mode 100644 example/runner/runner.json diff --git a/example/runner/runner.go b/example/runner/runner.go new file mode 100644 index 0000000..46efe84 --- /dev/null +++ b/example/runner/runner.go @@ -0,0 +1,170 @@ +// Copyright 2015 Daniel Theophanes. +// Use of this source code is governed by a zlib-style +// license that can be found in the LICENSE file.package service + +// Simple service that only works by printing a log message every few seconds. +package main + +import ( + "encoding/json" + "flag" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + + "github.com/kardianos/osext" + "github.com/kardianos/service" +) + +type Config struct { + Name, DisplayName, Description string + + Dir string + Exec string + Args []string + Env []string +} + +var logger service.Logger + +type program struct { + exit chan struct{} + service service.Service + + *Config +} + +func (p *program) Start(s service.Service) error { + // Look for exec. + // Verify home directory. + fullExec, err := exec.LookPath(p.Exec) + if err != nil { + return fmt.Errorf("Failed to find executable %q: %v", p.Exec, err) + } + + cmd := exec.Command(fullExec, p.Args...) + cmd.Dir = p.Dir + cmd.Env = p.Env + + go p.run(cmd) + return nil +} +func (p *program) run(cmd *exec.Cmd) { + logger.Info("Starting ", p.DisplayName) + defer func() { + if service.Interactive() { + p.Stop(p.service) + } else { + p.service.Stop() + } + }() + + out, err := cmd.CombinedOutput() + if err != nil { + logger.Warningf("Error running: %v", err) + } + if len(out) != 0 { + logger.Info(string(out)) + } + + return +} +func (p *program) Stop(s service.Service) error { + close(p.exit) + logger.Info("Stopping ", p.DisplayName) + if service.Interactive() { + os.Exit(0) + } + return nil +} + +func getConfigPath() (string, error) { + fullexecpath, err := osext.Executable() + if err != nil { + return "", err + } + + dir, execname := filepath.Split(fullexecpath) + ext := filepath.Ext(execname) + name := execname[:len(execname)-len(ext)] + + return filepath.Join(dir, name+".json"), nil +} + +func getConfig(path string) (*Config, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + conf := &Config{} + + r := json.NewDecoder(f) + err = r.Decode(&conf) + if err != nil { + return nil, err + } + return conf, nil +} + +func main() { + svcFlag := flag.String("service", "", "Control the system service.") + flag.Parse() + + configPath, err := getConfigPath() + if err != nil { + log.Fatal(err) + } + config, err := getConfig(configPath) + if err != nil { + log.Fatal(err) + } + + svcConfig := &service.Config{ + Name: config.Name, + DisplayName: config.DisplayName, + Description: config.Description, + } + + prg := &program{ + exit: make(chan struct{}), + + Config: config, + } + s, err := service.New(prg, svcConfig) + if err != nil { + log.Fatal(err) + } + prg.service = s + + errs := make(chan error, 5) + logger, err = s.Logger(errs) + if err != nil { + log.Fatal(err) + } + + go func() { + for { + err := <-errs + if err != nil { + log.Print(err) + } + } + }() + + if len(*svcFlag) != 0 { + err := service.Control(s, *svcFlag) + if err != nil { + log.Printf("Valid actions: %q\n", service.ControlAction) + log.Fatal(err) + } + return + } + err = s.Run() + if err != nil { + logger.Error(err) + } +} diff --git a/example/runner/runner.json b/example/runner/runner.json new file mode 100644 index 0000000..ed1bbaf --- /dev/null +++ b/example/runner/runner.json @@ -0,0 +1,15 @@ +{ + "Name": "builder", + "DisplayName": "Go Builder", + "Description": "Run the Go Builder", + + "Dir": "C:\\dev\\go\\src", + "Exec": "C:\\windows\\system32\\cmd.exe", + "Args": ["/C","C:\\dev\\go\\src\\all.bat"], + "Env": [ + "PATH=C:\\TDM-GCC-64\\bin;C:\\Program Files (x86)\\Git\\cmd", + "GOROOT_BOOTSTRAP=C:\\dev\\go_ready", + "HOMEDRIVE=C:", + "HOMEPATH=\\Documents and Settings\\Administrator" + ] +} \ No newline at end of file