예제 #1
0
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
}
예제 #2
0
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
}
예제 #3
0
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
}
예제 #4
0
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
}