Example #1
0
//CheckService accepts a command and returns a status code, output (stdout) and the reaction time
func CheckService(timeout int, command string) (status int, output string, rtime int64) {
	// Initialization.
	now := time.Now()

	//Convert executable to Go's os/exec.Command
	commandSlice := str.ToArgv(configuration.C.Paths.Checks + "/" + command)
	status, output = Execute(timeout, commandSlice[0], commandSlice[1:len(commandSlice)]...)

	//TODO: implement error logging
	elapsedTime := time.Since(now)
	elapsedTimeHuman := elapsedTime.Nanoseconds() / 1000000

	symbol := message.StatusColor("●", status)
	log.Debug(symbol + " (" + strconv.Itoa(status) + ") - " + command + " - " + output)

	return status, output, elapsedTimeHuman
}
Example #2
0
// parseStringEnv parse the package Env string and converts it into an
// environment slice.
func parseStringEnv(s string) []string {
	env := []string{}

	if s == "" {
		return env
	}

	s = str.Clean(s)
	argv := str.ToArgv(s)
	for _, kv := range argv {
		if !strings.Contains(kv, "=") {
			continue
		}
		env = append(env, kv)
	}
	return env
}
Example #3
0
func splitCommand(command string) (executable string, argv, env []string) {
	argv = str.ToArgv(command)
	for i, item := range argv {
		if strings.Contains(item, "=") {
			if env == nil {
				env = []string{item}
				continue
			}
			env = append(env, item)
		} else {
			executable = item
			argv = argv[i+1:]
			return
		}
	}

	executable = argv[0]
	argv = argv[1:]
	return
}
Example #4
0
// PartitionKV parses a reader for sections reder for lines containing a prefix and assingment.
func PartitionKV(r io.Reader, prefix string, assignment string) ([]map[string]string, error) {
	scanner := bufio.NewScanner(r)
	var buf bytes.Buffer
	var kv string
	var text string
	var result []map[string]string
	collect := false

	parseKV := func(kv string) {
		argv := str.ToArgv(kv)
		body := buf.String()
		for i, arg := range argv {
			m := map[string]string{}
			var key string
			var value string
			if strings.Contains(arg, assignment) {
				parts := strings.Split(arg, assignment)
				key = parts[0]
				value = parts[1]
			} else {
				key = arg
				value = ""
			}
			m[key] = value
			m["_body"] = body
			if i == 0 {
				m["_kind"] = key
			}
			result = append(result, m)
		}
	}

	for scanner.Scan() {
		text = scanner.Text()
		if strings.HasPrefix(text, prefix) {
			if kv != "" {
				parseKV(kv)
			}
			kv = text[len(prefix):]
			collect = true
			buf.Reset()
			continue
		}
		if collect {
			buf.WriteString(text)
			buf.WriteRune('\n')
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}

	if kv != "" && buf.Len() > 0 {
		parseKV(kv)
	}

	if collect {
		return result, nil
	}

	return nil, nil
}
Example #5
0
func (nagiosCheck *NagiosCheck) Check() (events []common.MapStr, err error) {

	startTime := time.Now()
	startMs := startTime.UnixNano() / int64(time.Millisecond)

	check_event := common.MapStr{
		"@timestamp": common.Time(startTime),
		"type":       "nagioscheck",
		"name":       nagiosCheck.name,
		"cmd":        nagiosCheck.cmd,
		"args":       nagiosCheck.args,
	}

	logp.Debug("nagioscheck", "Running Command: %q", nagiosCheck.cmd)

	arg_fields := str.ToArgv(nagiosCheck.args)

	cmd := exec.Command(nagiosCheck.cmd, arg_fields...)
	var waitStatus syscall.WaitStatus

	/* Go will return 'err' if the command exits abnormally (non-zero return code).
	Nagios commands always will exit abnormally when a check fails, so from
	a funcational perspective, this doesn't help us.  Instead, if the ProcessState is nil,
	that tells us that the command coulnd't run for some reason, which does help.
	*/

	output, err := cmd.CombinedOutput()
	if cmd.ProcessState == nil {
		return
	}

	waitStatus = cmd.ProcessState.Sys().(syscall.WaitStatus)

	logp.Debug("nagioscheck", "Command Returned: %q, exit code %d", output, waitStatus.ExitStatus())

	parts := strings.Split(string(output), "|")
	check_event["message"] = parts[0]
	check_event["status"] = nagiosperf.NiceStatus(waitStatus.ExitStatus())
	check_event["took_ms"] = time.Now().UnixNano()/int64(time.Millisecond) - startMs

	// publish the check result, even if there is no perf data
	events = append(events, check_event)

	if len(parts) > 1 {
		logp.Debug("nagioscheck", "Parsing: %q", parts[1])
		perfs, errors := nagiosperf.ParsePerfString(parts[1])
		if len(errors) > 0 {
			for _, err := range errors {
				logp.Debug("parse_errors", "Parse Error: %v", err)
			}
		}

		logp.Debug("nagioscheck", "Command Returned '%d' Perf Metrics: %v", len(perfs), perfs)

		for _, perf := range perfs {

			metric_event := common.MapStr{
				"@timestamp": common.Time(startTime),
				"type":       "nagiosmetric",
				"name":       nagiosCheck.name,
				"label":      perf.Label,
				"uom":        perf.Uom,
				"value":      perf.Value,
				"min":        perf.Min,
				"max":        perf.Max,
				"warning":    perf.Warning,
				"critical":   perf.Critical,
			}

			events = append(events, metric_event)

		}
	}

	return
}
Example #6
0
/*
Splits string by spaces, ignoring spaces between quotes
*/
func eachPerf(perfString string) []string {
	return str.ToArgv(perfString)
}