github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmg/SubCommand/serviceCmd/command.go.bak (about)

     1  package serviceCommand
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"github.com/bronze1man/kmg/kmgConsole"
     7  	"github.com/kardianos/service"
     8  	"os"
     9  	"os/exec"
    10  	"runtime"
    11  	"strings"
    12  )
    13  
    14  //TODO 统一进程输出的输出位置,默认不区分err和out.
    15  //TODO 添加stopanduninstall命令(停掉,并且卸载),删除或隐藏其他无用命令
    16  
    17  //TODO 添加至少一个平台的测试
    18  //TODO kmg gorun 可以在service运行的进程里面,目前是restart 存在bug
    19  //TODO 完整描述使用过程
    20  //TODO 在osx和linux上达到一致的行为
    21  
    22  func init() {
    23  	kmgConsole.AddAction(kmgConsole.Command{
    24  		Name:   "Service.SetAndRestart",
    25  		Desc:   "install the service,and restart the service,uninstall and stop if need",
    26  		Runner: setAndRestartCmd,
    27  	})
    28  	kmgConsole.AddAction(kmgConsole.Command{
    29  		Name:   "Service.Install",
    30  		Desc:   "install the service",
    31  		Runner: installCmd,
    32  	})
    33  	kmgConsole.AddAction(kmgConsole.Command{
    34  		Name:   "Service.Uninstall",
    35  		Desc:   "uninstall the serivce",
    36  		Runner: newNameCmd(func(s service.Service) error { return s.Uninstall() }),
    37  	})
    38  	kmgConsole.AddAction(kmgConsole.Command{
    39  		Name:   "Service.Start",
    40  		Desc:   "start the service",
    41  		Runner: newNameCmd(func(s service.Service) error { return s.Start() }),
    42  	})
    43  	kmgConsole.AddAction(kmgConsole.Command{
    44  		Name:   "Service.Stop",
    45  		Desc:   "start the service",
    46  		Runner: newNameCmd(func(s service.Service) error { return s.Stop() }),
    47  	})
    48  	kmgConsole.AddAction(kmgConsole.Command{
    49  		Name:   "Service.Restart",
    50  		Desc:   "restart the service,if the service is not running,start it.",
    51  		Runner: newNameCmd(kmgRestart),
    52  	})
    53  }
    54  
    55  type installRequest struct {
    56  	Name             string   //名字
    57  	ExecuteArgs      []string //执行的命令,第一个是执行命令的进程地址
    58  	WorkingDirectory string   //工作目录(默认是当前目录) 不能在upstart系统上面运行
    59  	//有下列选项
    60  	// 'Darwin Launchd'
    61  	// 'systemd'
    62  	// 'Upstart'
    63  	// 'System-V'
    64  	// 'Windows Service'
    65  	SystemName string //使用的系统(linux上面可以进行选择)
    66  }
    67  
    68  func setAndRestartCmd() {
    69  	s, err := parseInstallRequest()
    70  	kmgConsole.ExitOnErr(err)
    71  	err = s.Install()
    72  	if err != nil {
    73  		if !strings.Contains(err.Error(), "already exists") {
    74  			kmgConsole.ExitOnErr(err)
    75  		}
    76  		err = s.Uninstall()
    77  		kmgConsole.ExitOnErr(err)
    78  		err = s.Install()
    79  		kmgConsole.ExitOnErr(err)
    80  	}
    81  	err = kmgRestart(s)
    82  	kmgConsole.ExitOnErr(err)
    83  }
    84  
    85  func installCmd() {
    86  	s, err := parseInstallRequest()
    87  	kmgConsole.ExitOnErr(err)
    88  	err = s.Install()
    89  	kmgConsole.ExitOnErr(err)
    90  }
    91  
    92  func parseInstallRequest() (s service.Service, err error) {
    93  	req := &installRequest{}
    94  	flag.StringVar(&req.Name, "name", "", "name of the service(require)")
    95  	var executeString string
    96  	flag.StringVar(&executeString, "exec", "", "command to run(require,use ' ' to separate args)")
    97  	flag.StringVar(&req.WorkingDirectory, "cd", "", "working directory(optional),default to currend directory")
    98  	flag.StringVar(&req.SystemName, "system", "", "system name")
    99  	flag.Parse()
   100  	if req.Name == "" {
   101  		return nil, fmt.Errorf("require name args")
   102  	}
   103  	if executeString == "" {
   104  		return nil, fmt.Errorf("require exec args")
   105  	}
   106  	req.ExecuteArgs = strings.Split(executeString, " ")
   107  	req.ExecuteArgs[0], err = exec.LookPath(req.ExecuteArgs[0])
   108  	kmgConsole.ExitOnErr(err)
   109  	if req.WorkingDirectory == "" {
   110  		req.WorkingDirectory, err = os.Getwd()
   111  		if err != nil {
   112  			return nil, err
   113  		}
   114  	}
   115  	svcConfig := &service.Config{
   116  		Name:             req.Name,
   117  		Executable:       req.ExecuteArgs[0],
   118  		Arguments:        req.ExecuteArgs[1:],
   119  		WorkingDirectory: req.WorkingDirectory,
   120  		Option: service.KeyValue{
   121  			"KeepAlive": false,
   122  		},
   123  	}
   124  	system, err := chooseSystem(req.SystemName)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	return system.New(nil, svcConfig)
   129  
   130  }
   131  
   132  func newNameCmd(fn func(s service.Service) error) func() {
   133  	return func() {
   134  		req := installRequest{}
   135  		flag.StringVar(&req.Name, "name", "", "name of the service(require)")
   136  		flag.StringVar(&req.SystemName, "system", "", "system name")
   137  		flag.Parse()
   138  		name := ""
   139  		switch {
   140  		case req.Name != "":
   141  			name = req.Name
   142  		case flag.Arg(0) != "":
   143  			name = flag.Arg(0)
   144  		default:
   145  			fmt.Println("require name args")
   146  			flag.Usage()
   147  			return
   148  		}
   149  		svcConfig := &service.Config{
   150  			Name: name,
   151  		}
   152  		system, err := chooseSystem(req.SystemName)
   153  		kmgConsole.ExitOnErr(err)
   154  
   155  		s, err := system.New(nil, svcConfig)
   156  		kmgConsole.ExitOnErr(err)
   157  		err = fn(s)
   158  		kmgConsole.ExitOnErr(err)
   159  	}
   160  }
   161  
   162  // 允许 stop restart 这种用法
   163  func kmgRestart(s service.Service) (err error) {
   164  	err = s.Stop()
   165  	if err != nil {
   166  		errS := err.Error()
   167  		if !(strings.Contains(errS, "Unknown instance")) {
   168  			return err
   169  		}
   170  	}
   171  	err = s.Start()
   172  	return err
   173  }
   174  
   175  func chooseSystem(SystemName string) (sys service.System, err error) {
   176  	if runtime.GOOS == "linux" && SystemName == "" {
   177  		SystemName = "System-V"
   178  	}
   179  	if SystemName == "" {
   180  		return service.ChosenSystem(), nil
   181  	}
   182  	avaliableListS := ""
   183  	for _, thisSystem := range service.AvailableSystems() {
   184  		if !thisSystem.Detect() {
   185  			continue
   186  		}
   187  		avaliableListS += thisSystem.String() + ","
   188  		if thisSystem.String() == SystemName {
   189  			return thisSystem, nil
   190  		}
   191  	}
   192  	return nil, fmt.Errorf("system [%s] not exist,avaliable:[%s]", SystemName, avaliableListS)
   193  
   194  }