func clientMain(addr string, args []string) (bool, error) { createGovernatorUserDir() if len(args) > 0 { return evalCommand(addr, args) } r := newLineReader() fmt.Printf("%s interactive shell\nType exit or press control+d to end\nType help to show available commands\n\n", AppName) sendCommand(addr, []string{"list"}) for { s, err := r.ReadLine() if err == io.EOF { fmt.Print("exit\n") break } s = strings.TrimSpace(s) if s != "" { r.AddHistory(s) fields, err := stringutil.SplitFields(s, " ") if err != nil { fmt.Fprintf(os.Stderr, "error reading input: %s\n", err) continue } if _, err := evalCommand(addr, fields); err != nil { fmt.Fprintf(os.Stderr, "error executing command: %s\n", err) } } } return true, nil }
func (w *Watchdog) Parse(input string) error { if input == "" { return nil } args, err := stringutil.SplitFields(input, " ") if err != nil { return err } if len(args) > 0 { switch args[0] { case "run": if len(args) == 1 { return fmt.Errorf("run watchdog requires at least one argument") } w.dog = &runDog{args[1:]} case "connect": if len(args) != 2 && len(args) != 3 { return fmt.Errorf("connect watchdog requires one or two arguments, %d given", len(args)) } u, err := url.Parse(args[1]) if err != nil { return fmt.Errorf("invalid connect URL %q: %s", args[1], err) } if u.Scheme != "tcp" && u.Scheme != "udp" { return fmt.Errorf("invalid connect URL scheme %q - must be tcp or udp", u.Scheme) } if _, _, err := net.SplitHostPort(u.Host); err != nil { return fmt.Errorf("address %q must specifiy a host and a port", u.Host) } timeout, err := getTimeout("connect", args) if err != nil { return err } w.dog = &connectDog{u.Scheme, u.Host, timeout} case "get": if len(args) != 2 && len(args) != 3 { return fmt.Errorf("get watchdog requires two or three arguments, %d given", len(args)) } u, err := url.Parse(args[1]) if err != nil { return fmt.Errorf("invalid GET URL %q: %s", args[1], err) } if u.Scheme != "http" && u.Scheme != "https" { return fmt.Errorf("invalid GET URL scheme %q - must be http or https", u.Scheme) } timeout, err := getTimeout("get", args) if err != nil { return err } w.dog = &getDog{args[1], timeout} } } if w.dog == nil { return fmt.Errorf("invalid watchdog %q - available watchdogs are run, connect and get", input) } return nil }
func (c *Config) Cmd() (*exec.Cmd, error) { if c.Err != nil { return nil, c.Err } if c.Command == "" { return nil, fmt.Errorf("no command") } fields, err := stringutil.SplitFields(c.Command, " ") if err != nil { return nil, err } if !filepath.IsAbs(fields[0]) { p, err := exec.LookPath(fields[0]) if err != nil { return nil, err } fields[0] = p } dir := c.Dir if dir == "" { dir = filepath.Dir(fields[0]) } cmd := &exec.Cmd{Path: fields[0], Args: fields, Dir: dir} for k, v := range c.Env { cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, v)) } if _, ok := c.Env["GOMAXPROCS"]; !ok { cmd.Env = append(cmd.Env, fmt.Sprintf("GOMAXPROCS=%d", runtime.NumCPU())) } for _, v := range os.Environ() { if p := strings.IndexByte(v, '='); p >= 0 { k := v[:p] if _, ok := c.Env[k]; !ok { cmd.Env = append(cmd.Env, v) } } } info, err := os.Stat(fields[0]) if err != nil { return nil, err } stat := info.Sys().(*syscall.Stat_t) uid := stat.Uid gid := stat.Gid if c.Group != "" { if g := getGroupId(c.Group); g > 0 { gid = uint32(g) } else { return nil, fmt.Errorf("invalid group %q", c.Group) } } if c.User != "" { u, err := user.Lookup(c.User) if err != nil { return nil, err } ui, _ := strconv.Atoi(u.Uid) uid = uint32(ui) if gid == 0 { gi, _ := strconv.Atoi(u.Gid) gid = uint32(gi) } } var cred *syscall.Credential if uid != 0 || gid != 0 { cred = &syscall.Credential{Uid: uid, Gid: gid} } attr := &syscall.SysProcAttr{ Credential: cred, } prepareSysProcAttr(attr) cmd.SysProcAttr = attr log.Debugf("%s wd: %s, env: %s, cred: %+v", c.ServiceName(), dir, cmd.Env, cred) return cmd, nil }
func (l *Logger) Parse(input string) error { if input == "" { input = "file" } args, err := stringutil.SplitFields(input, " ") if err != nil { return err } switch strings.ToLower(args[0]) { case "file": maxSize := uint64(500 * 1024 * 1024) // 500MB count := 10 // 10 rotated files switch len(args) { case 1: break case 3: c, err := strconv.Atoi(args[2]) if err != nil { return fmt.Errorf("invalid file count %q, must be an integer", args[2]) } count = c fallthrough case 2: size, err := parseutil.Size(args[1]) if err != nil { return err } maxSize = size default: return fmt.Errorf("invalid number of arguments for file logger - must be one or two, %d given", len(args)-1) } l.w = &fileWriter{dir: logDir, maxSize: maxSize, count: count} case "syslog": var scheme string var addr string switch len(args) { case 1: break case 2: u, err := url.Parse(args[1]) if err != nil { return fmt.Errorf("invalid syslog URL %q: %s", args[1], err) } if u.User != nil || u.Path != "" || u.RawQuery != "" || u.Fragment != "" { return fmt.Errorf("invalid syslog URL %q: must not have user, nor path, nor query, nor fragment", args[1]) } if u.Scheme == "" { return fmt.Errorf("invalid syslog URL %q: scheme can't be empty", args[1]) } if u.Host == "" { return fmt.Errorf("invalid syslog URL %q: host can't be empty", args[1]) } scheme = u.Scheme addr = u.Host default: return fmt.Errorf("invalid number of arguments for syslog logger - must be zero or one, %d given", len(args)-1) } l.w = &syslogWriter{scheme: scheme, addr: addr} case "none": l.w = &noneWriter{} default: return fmt.Errorf("invalid logger %s", args[0]) } l.Stdout = &Out{Logger: l, prefix: "stdout"} l.Stderr = &Out{Logger: l, prefix: "stderr"} return nil }