Example #1
0
// how many inodes are in this given state? state can be one of:
// total, used, free, percent
func inodesInState(filesystem, state string) (total uint64, err error) {
	cmd := exec.Command("df", "-i")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return total, err
	}
	table := tabular.ProbabalisticSplit(string(out))
	filesystems := tabular.GetColumnByHeader("Filesystem", table)
	var totals []string
	switch state {
	case "total":
		totals = tabular.GetColumnByHeader("Inodes", table)
	case "free":
		totals = tabular.GetColumnByHeader("IFree", table)
	case "used":
		totals = tabular.GetColumnByHeader("IUsed", table)
	case "percent":
		totals = tabular.GetColumnByHeader("IUse%", table)
	default:
		formatStr := "Internal error: unexpected state in inodesInState: %v"
		return total, fmt.Errorf(formatStr, state)
	}
	if len(filesystems) != len(totals) {
		formatStr := "The number of filesystems (%d) didn't match the number of"
		formatStr += " inode totals (%d)!"
		return total, fmt.Errorf(formatStr, len(filesystems), len(totals))
	}
	for i := range totals {
		if filesystems[i] == filesystem {
			// trim the % in case the state was "percent"
			return strconv.ParseUint(strings.TrimSuffix(totals[i], "%"), 10, 64)
		}
	}
	return total, fmt.Errorf("Couldn't find that filesystem: " + filesystem)
}
Example #2
0
// GetHexPorts gets all open ports as hex strings from /proc/net/{tcp,udp}
// Its protocol argument can only be one of: "tcp" | "udp"
func GetHexPorts(protocol string) (ports []string) {
	var path string
	switch strings.ToLower(protocol) {
	case "tcp":
		path = "/proc/net/tcp"
	case "udp":
		path = "/proc/net/udp"
	default:
		log.WithFields(log.Fields{
			"protocol":        protocol,
			"valid protocols": "tcp|udp",
		}).Fatal("Invalid protocol passed to GetHexPorts!")
	}
	data := chkutil.FileToString(path)
	rowSep := regexp.MustCompile(`\n+`)
	colSep := regexp.MustCompile(`\s+`)
	table := tabular.SeparateString(rowSep, colSep, data)
	localAddresses := tabular.GetColumnByHeader("local_address", table)
	portRe := regexp.MustCompile(`([0-9A-F]{8}):([0-9A-F]{4})`)
	for _, address := range localAddresses {
		port := portRe.FindString(address)
		if port != "" {
			if len(port) < 10 {
				log.WithFields(log.Fields{
					"port":   port,
					"length": len(port),
				}).Fatal("Couldn't parse port number in " + path)
			}
			portString := string(port[9:])
			ports = append(ports, portString)
		}
	}
	return ports
}
// ListeningSockets returns a list of all sockets in the "LISTENING" state
func ListeningSockets() (socks []string, err error) {
	out, err := exec.Command("systemctl", "list-sockets").CombinedOutput()
	if err != nil {
		return socks, errors.New(err.Error() + ": output: " + string(out))
	}
	table := tabular.ProbabalisticSplit(string(out))
	return tabular.GetColumnByHeader("LISTENING", table), nil
}
Example #4
0
// DockerImageRepositories returns a slice of the names of the Docker images
// present on the host (what's under the REPOSITORIES column of `docker images`)
func DockerImageRepositories() (images []string, err error) {
	cmd := exec.Command("docker", "images")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return images, err
	}
	table := tabular.ProbabalisticSplit(string(out))
	return tabular.GetColumnByHeader("REPOSITORIES", table), nil
}
Example #5
0
// RunningContainers returns a list of names of running docker containers
// (what's under the IMAGE column of `docker ps -a` if it has status "Up".
func RunningContainers() (containers []string, err error) {
	cmd := exec.Command("docker", "ps", "-a")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return containers, err
	}
	// the output of `docker ps -a` has spaces in columns, but each column
	// is separated by 2 or more spaces. Just what Probabalistic was made for!
	lines := tabular.ProbabalisticSplit(string(out))
	names := tabular.GetColumnByHeader("IMAGE", lines)
	statuses := tabular.GetColumnByHeader("STATUS", lines)
	for i, status := range statuses {
		// index error caught by second condition in if clause
		if strings.Contains(status, "Up") && len(names) > i {
			containers = append(containers, names[i])
		}
	}
	return containers, nil
}
Example #6
0
// swapOrMemory returns output from `free`, it is an abstraction of swap and
// memory. inputs: status: free | used | total; swapOrMem: memory | swap;
// units: b | kb | mb | gb | tb
func swapOrMemory(status string, swapOrMem string, units string) (int, error) {
	unitsToFlag := map[string]string{
		"b":  "--bytes",
		"kb": "--kilo",
		"mb": "--mega",
		"gb": "--giga",
		"tb": "--tera",
	}
	typeToRow := map[string]int{
		"memory": 0,
		"swap":   1,
	}
	// check to see that our keys are really in our dict
	if _, ok := unitsToFlag[units]; !ok {
		return 0, errors.New("Invalid units in swapOrMemory: " + units)
	} else if _, ok := typeToRow[swapOrMem]; !ok {
		return 0, errors.New("Invalid option in swapOrMemory: " + swapOrMem)
	}
	// execute free and return the appropriate output
	cmd := exec.Command("free", unitsToFlag[units])
	out, err := cmd.CombinedOutput()
	if err != nil {
		return 0, err
	}
	// TODO probabalisticsplit isn't handling this appropriately
	//table := tabular.ProbabalisticSplit(outStr)
	colSep := regexp.MustCompile(`\s+`)
	rowSep := regexp.MustCompile(`\n+`)
	table := tabular.SeparateString(rowSep, colSep, string(out))
	column := tabular.GetColumnByHeader(status, table)

	// filter out useless row from some versions of `free`
	for i, row := range table {
		if len(row) > 0 && strings.Contains(row[0], "-/+") {
			table = append(table[:i], table[i+1:]...)
		}
	}

	row := typeToRow[swapOrMem]
	// check for errors in output of `free`
	if column == nil || len(column) < 1 {
		errors.New("Free column was empty")
	}
	if row >= len(column) {
		errors.New("`free` didn't output enough rows")
	}
	toReturn, err := strconv.ParseInt(column[row], 10, 64)
	if err != nil {
		errors.New("Couldn't parse output of `free` as an int")
	}
	return int(toReturn), nil
}
Example #7
0
// returns a column of the routing table as a slice of strings
func routingTableColumn(name string) []string {
	cmd := exec.Command("route", "-n")
	out := wrkutils.CommandOutput(cmd)
	table := tabular.ProbabalisticSplit(out)
	if len(table) < 1 {
		log.WithFields(log.Fields{
			"column": name,
			"table":  "\n" + tabular.ToString(table),
		}).Fatal("Routing table was not available or not properly parsed")
	}
	finalTable := table[1:] // has extra line before headers
	return tabular.GetColumnByHeader(name, finalTable)
}
Example #8
0
// systemctlSock is an abstraction of systemctlSockPath and systemctlSockUnit,
// it reads from `systemctl list-sockets` and sees if the value is in the
// appropriate column.
func systemctlSock(value string, column string) (exitCode int, exitMessage string) {
	outstr := wrkutils.CommandOutput(exec.Command("systemctl", "list-sockets"))
	lines := tabular.Lines(outstr)
	msg := "systemctl list-sockers didn't output enough rows"
	wrkutils.IndexError(msg, len(lines)-4, lines)
	unlines := tabular.Unlines(lines[:len(lines)-4])
	table := tabular.SeparateOnAlignment(unlines)
	values := tabular.GetColumnByHeader(column, table)
	if tabular.StrIn(value, values) {
		return 0, ""
	}
	return wrkutils.GenericError("Socket not found", value, values)
}
// DockerImageRepositories returns a slice of the names of the Docker images
// present on the host (what's under the REPOSITORIES column of `docker images`)
func DockerImageRepositories() (images []string, err error) {
	cmd := exec.Command("docker", "images")
	out, err := cmd.CombinedOutput()
	if err != nil {
		// try escalating to sudo, the error might have been one of permissions
		cmd = exec.Command("sudo", "docker", "images")
		out, err = cmd.CombinedOutput()
		if err != nil {
			return images, err
		}
	}
	table := tabular.ProbabalisticSplit(string(out))
	return tabular.GetColumnByHeader("REPOSITORY", table), nil
}
Example #10
0
// getTimers returns of all the timers under the UNIT column of
// `systemctl list-timers`
func getTimers(all bool) []string {
	cmd := exec.Command("systemctl", "list-timers")
	if all {
		cmd = exec.Command("systemctl", "list-timers", "--all")
	}
	out, err := cmd.CombinedOutput()
	outstr := string(out)
	wrkutils.ExecError(cmd, outstr, err)
	// last three lines are junk
	lines := tabular.Lines(outstr)
	msg := fmt.Sprint(cmd.Args) + " didn't output enough lines"
	wrkutils.IndexError(msg, 3, lines)
	table := tabular.SeparateOnAlignment(tabular.Unlines(lines[:len(lines)-3]))
	column := tabular.GetColumnByHeader("UNIT", table)
	return column
}
// Timers returns a list of the active systemd timers, as found under the
// UNIT column of `systemctl list-timers`. It can optionally list all timers.
func Timers(all bool) (timers []string, err error) {
	cmd := exec.Command("systemctl", "list-timers")
	if all {
		cmd = exec.Command("systemctl", "list-timers", "--all")
	}
	out, err := cmd.CombinedOutput()
	if err != nil {
		return timers, errors.New(err.Error() + ": output: " + string(out))
	}
	// last three lines are junk
	lines := tabular.Lines(string(out))
	if len(lines) <= 3 {
		msg := fmt.Sprint(cmd.Args) + " didn't output enough lines"
		return timers, errors.New(msg)
	}
	table := tabular.SeparateOnAlignment(tabular.Unlines(lines[:len(lines)-3]))
	column := tabular.GetColumnByHeader("UNIT", table)
	return column, nil
}
Example #12
0
// getSwapOrMemory returns output from `free`, it is an abstraction of
// getSwap and getMemory. inputs: status: free | used | total
// swapOrMem: memory | swap, units: b | kb | mb | gb | tb
// TODO: support kib/gib style units, with proper transformations.
func getSwapOrMemory(status string, swapOrMem string, units string) int {
	statusToColumn := map[string]int{
		"total": 1,
		"used":  2,
		"free":  3,
	}
	unitsToFlag := map[string]string{
		"b":  "--bytes",
		"kb": "--kilo",
		"mb": "--mega",
		"gb": "--giga",
		"tb": "--tera",
	}
	typeToRow := map[string]int{
		"memory": 0,
		"swap":   1,
	}
	// check to see that our keys are really in our dict
	if _, ok := statusToColumn[status]; !ok {
		log.WithFields(log.Fields{
			"status":   status,
			"expected": []string{"total", "used", "free"},
		}).Fatal("Internal error: invalid status in getSwapOrMemory")
	} else if _, ok := unitsToFlag[units]; !ok {
		log.WithFields(log.Fields{
			"units":    units,
			"expected": []string{"b", "kb", "mb", "gb", "tb"},
		}).Fatal("Internal error: invalid units in getSwapOrMemory")
	} else if _, ok := typeToRow[swapOrMem]; !ok {
		log.WithFields(log.Fields{
			"option":   swapOrMem,
			"expected": []string{"memory", "swap"},
		}).Fatal("Internal error: invalid option in getSwapOrMemory")
	}
	// execute free and return the appropriate output
	cmd := exec.Command("free", unitsToFlag[units])
	outStr := wrkutils.CommandOutput(cmd)
	table := tabular.ProbabalisticSplit(outStr)
	column := tabular.GetColumnByHeader(status, table)
	row := typeToRow[swapOrMem]
	// check for errors in output of `free`
	if column == nil {
		log.WithFields(log.Fields{
			"header": status,
			"table":  "\n" + tabular.ToString(table),
		}).Fatal("Free column was empty")
	}
	if row >= len(column) {
		log.WithFields(log.Fields{
			"output": outStr,
			"column": column,
			"row":    row,
		}).Fatal("`free` didn't output enough rows")
	}
	toReturn, err := strconv.ParseInt(column[row], 10, 64)
	if err != nil {
		log.WithFields(log.Fields{
			"cell":   column[row],
			"error":  err.Error(),
			"output": outStr,
		}).Fatal("Couldn't parse output of `free` as an int")
	}
	return int(toReturn)
}