func (l *Launchd) Restart(serviceName string) error { path := l.resolvePlist(serviceName) if path == "" { return &ServiceError{l.Name(), serviceName, ErrServiceNotFound} } cmd := exec.Command("launchctl", "unload", path) sout, err := util.SafeRun(cmd) if err != nil { return &ServiceError{l.Name(), serviceName, err} } lines, err := util.ReadLines(sout) if len(lines) != 0 { return &ServiceError{l.Name(), serviceName, errors.New("Unexpected output: " + strings.Join(lines, "\n"))} } cmd = exec.Command("launchctl", "load", path) sout, err = util.SafeRun(cmd) if err != nil { return &ServiceError{l.Name(), serviceName, err} } lines, err = util.ReadLines(sout) if len(lines) != 0 { return &ServiceError{l.Name(), serviceName, errors.New("Unexpected output: " + strings.Join(lines, "\n"))} } return nil }
func (l *Launchd) LookupService(serviceName string) (*ProcessStatus, error) { cmd := exec.Command("launchctl", "list") sout, err := util.SafeRun(cmd) if err != nil { return nil, &ServiceError{l.Name(), serviceName, err} } lines, err := util.ReadLines(sout) if err != nil { return nil, &ServiceError{l.Name(), serviceName, err} } for _, line := range lines { if strings.Contains(line, serviceName) { util.Debug("launchctl found " + serviceName) parts := strings.SplitN(line, "\t", 3) pid, err := strconv.ParseInt(parts[0], 10, 32) if err != nil { return nil, &ServiceError{l.Name(), serviceName, err} } return &ProcessStatus{int(pid), Up}, nil } } path := l.resolvePlist(serviceName) if path != "" { return &ProcessStatus{0, Down}, nil } return nil, &ServiceError{l.Name(), serviceName, ErrServiceNotFound} }
func (s *Systemd) LookupService(serviceName string) (*ProcessStatus, error) { var sout []byte var err error if len(s.dummyOutput) != 0 { sout = []byte(s.dummyOutput) } else { cmd := exec.Command("systemctl", "show", "-p", "MainPID", serviceName) sout, err = util.SafeRun(cmd) } if err != nil { return nil, &ServiceError{s.Name(), serviceName, ErrServiceNotFound} } lines, err := util.ReadLines(sout) if len(lines) != 1 { return nil, &ServiceError{s.Name(), serviceName, errors.New("Unexpected output: " + strings.Join(lines, "\n"))} } // Output will be "MainPID=1234" or // "MainPID=0" if service does not exist. line := lines[0] fields := strings.Split(line, "=") if fields[1] != "0" { pid, err := strconv.ParseInt(fields[1], 10, 32) if err != nil { return nil, &ServiceError{s.Name(), serviceName, err} } return &ProcessStatus{int(pid), Up}, nil } if len(s.dummyOutput2) != 0 { sout = []byte(s.dummyOutput2) } else { cmd := exec.Command("systemctl", "is-enabled", serviceName) sout, err = util.SafeRun(cmd) } if err != nil || string(sout) != "enabled\n" { return nil, &ServiceError{s.Name(), serviceName, ErrServiceNotFound} } return &ProcessStatus{0, Down}, nil }
func (u *Upstart) LookupService(serviceName string) (*ProcessStatus, error) { matches, err := filepath.Glob(u.path + "/" + serviceName + ".conf") if err != nil { return nil, &ServiceError{u.Name(), serviceName, err} } if len(matches) == 0 { return nil, &ServiceError{u.Name(), serviceName, ErrServiceNotFound} } var sout []byte if u.dummyOutput != nil { sout = []byte(*u.dummyOutput) } else { cmd := exec.Command("initctl", "status", serviceName) sout, err = util.SafeRun(cmd) if err != nil { return nil, &ServiceError{u.Name(), serviceName, err} } } lines, err := util.ReadLines(sout) if len(lines) != 1 { return nil, &ServiceError{u.Name(), serviceName, errors.New("Unexpected output: " + strings.Join(lines, "\n"))} } // mysql start/running, process 14190 // sshdgenkeys stop/waiting line := lines[0] if strings.Contains(line, "Unknown job") { return nil, &ServiceError{u.Name(), serviceName, ErrServiceNotFound} } results := pidScanner.FindStringSubmatch(line) if len(results) == 4 && len(results[3]) > 0 { pid, err := strconv.ParseInt(results[3], 10, 32) if err != nil { return nil, &ServiceError{u.Name(), serviceName, err} } return &ProcessStatus{int(pid), Up}, nil } if len(results) == 4 { switch { case results[1] == "start": return &ProcessStatus{0, Starting}, nil case results[1] == "stop": return &ProcessStatus{0, Down}, nil } } return nil, &ServiceError{u.Name(), serviceName, errors.New("Unknown upstart output: " + line)} }
func (i *Initd) serviceCommand(serviceName string, command string, timeout time.Duration) error { path := i.ctlPath + serviceName cmd := exec.Command(path, command) _, err := util.SafeRun(cmd, timeout) if err != nil { return &ServiceError{i.Name(), serviceName, err} } return nil }
func (s *Systemd) serviceCommand(serviceName string, command string, timeout time.Duration) error { if len(s.dummyOutput) == 0 { cmd := exec.Command("systemctl", command, serviceName) _, err := util.SafeRun(cmd, timeout) if err != nil { return &ServiceError{s.Name(), serviceName, err} } } return nil }
/* * So many hacks in this. OSX support can be seen as "bad" at best. */ func (ps *processStorage) capturePs(pid int) error { cmd := exec.Command("ps", "So", "rss,time,utime", "-p", strconv.Itoa(pid)) sout, err := util.SafeRun(cmd) if err != nil { return err } lines, err := util.ReadLines(sout) if err != nil { return err } if len(lines) < 2 { return errors.New("Insufficient output from ps") } fields := strings.Fields(lines[1]) val, err := strconv.ParseInt(fields[0], 10, 64) if err != nil { return err } ps.Save("memory", "rss", float64(1024*val)) times := timeRegexp.FindStringSubmatch(fields[1]) if times == nil { util.Debug("Unable to parse CPU time in " + lines[1]) return nil } min, _ := strconv.ParseUint(times[1], 10, 32) sec, _ := strconv.ParseUint(times[2], 10, 32) cs, _ := strconv.ParseUint(times[3], 10, 32) ticks := min*60*100 + sec*100 + cs times = timeRegexp.FindStringSubmatch(fields[2]) if times == nil { util.Debug("Unable to parse User time in " + lines[1]) return nil } min, _ = strconv.ParseUint(times[1], 10, 32) sec, _ = strconv.ParseUint(times[2], 10, 32) cs, _ = strconv.ParseUint(times[3], 10, 32) uticks := min*60*100 + sec*100 + cs ps.Save("cpu", "user", float64(uticks)) ps.Save("cpu", "system", float64(ticks-uticks)) return nil }
func (hs *hostStorage) collectDisk(path string) error { var lines []string if path == "" { cmd := exec.Command("df", "-P") sout, err := util.SafeRun(cmd) if err != nil { return err } lines, err = util.ReadLines(sout) if err != nil { return err } } else { data, err := ioutil.ReadFile(path) if err != nil { return err } lines, err = util.ReadLines(data) if err != nil { return err } } usage := map[string]float64{} for _, line := range lines { if line[0] == '/' { items := strings.Fields(line) if len(items) < 5 { util.Debug("Cannot parse df output: %v", items) continue } pct := items[4] if pct[len(pct)-1] == '%' { val, err := strconv.ParseInt(pct[0:len(pct)-1], 10, 32) if err != nil { util.Debug("Cannot parse df output: " + line) } usage[items[len(items)-1]] = float64(val) } } } for name, used := range usage { hs.saveType("disk", name, used, Gauge) } return nil }
func (hs *hostStorage) collectLoadAverage() error { // TODO make this a one-time check so we don't incur the overhead // on every cycle. ok, err := util.FileExists(hs.path + "/loadavg") if err != nil { return err } var loadavgString string if ok { contentBytes, err := ioutil.ReadFile(hs.path + "/loadavg") if err != nil { return err } loadavgString = string(contentBytes) } else { cmd := exec.Command("sysctl", "-n", "vm.loadavg") cmd.Env = []string{"LANG=C"} sout, err := util.SafeRun(cmd) if err != nil { return err } lines, err := util.ReadLines(sout) if err != nil { return err } loadavgString = lines[0][2 : len(lines[0])-2] // trim braces } slices := strings.Split(loadavgString, " ") load1, err := strconv.ParseFloat(slices[0], 64) if err != nil { return err } load5, err := strconv.ParseFloat(slices[1], 64) if err != nil { return err } load15, err := strconv.ParseFloat(slices[2], 64) if err != nil { return err } hs.Save("load", "1", load1) hs.Save("load", "5", load5) hs.Save("load", "15", load15) return nil }
func execCmd(command string, args []string, stdin []byte) ([]byte, error) { cmd := exec.Command(command, args...) if stdin != nil { in, err := cmd.StdinPipe() if err != nil { return nil, err } _, err = in.Write(stdin) in.Close() if err != nil { return nil, err } } return util.SafeRun(cmd) }
func (u *Upstart) serviceCommand(serviceName string, command string, timeout time.Duration, expectedLines int) error { var err error var sout []byte if u.dummyOutput != nil { sout = []byte(*u.dummyOutput) } else { cmd := exec.Command("initctl", command, serviceName) sout, err = util.SafeRun(cmd, timeout) if err != nil { return &ServiceError{u.Name(), serviceName, err} } } lines, err := util.ReadLines(sout) if len(lines) != expectedLines { return &ServiceError{u.Name(), serviceName, errors.New("Unexpected output: " + strings.Join(lines, "\n"))} } return nil }
func (hs *hostStorage) collectMemory() error { ok, err := util.FileExists(hs.path + "/meminfo") if err != nil { return err } if ok { contentBytes, err := ioutil.ReadFile(hs.path + "/meminfo") if err != nil { return err } lines := strings.Split(string(contentBytes), "\n") memMetrics := make(map[string]float64) for _, line := range lines { if line == "" { continue } results := meminfoParser.FindStringSubmatch(line) if results == nil { util.Warn("Unknown input: " + line) continue } val, err := strconv.ParseInt(results[2], 10, 64) if err != nil { util.Warn("Unexpected input: " + results[2] + " in " + line) return err } memMetrics[results[1]] = float64(val) } free := memMetrics["SwapFree"] total := memMetrics["SwapTotal"] if free == 0 { hs.Save("swap", "", 100) } else if free == total { hs.Save("swap", "", 0) } else { hs.Save("swap", "", float64(100-int8(100*(float64(free)/float64(total))))) } } else { cmd := exec.Command("sysctl", "-n", "vm.swapusage") cmd.Env = []string{"LANG=C"} sout, err := util.SafeRun(cmd) if err != nil { return err } lines, err := util.ReadLines(sout) if err != nil { return err } rest := lines[0] matches := swapRegexp.FindStringSubmatch(rest) total := matches[1] rest = matches[2] matches = swapRegexp.FindStringSubmatch(rest) used := matches[1] tot, err := strconv.ParseFloat(total[0:len(total)-1], 64) if err != nil { return err } usd, err := strconv.ParseFloat(used[0:len(used)-1], 64) if err != nil { return err } t := normalizeSwap(tot, rune(total[len(total)-1])) u := normalizeSwap(usd, rune(used[len(used)-1])) if t == 0 { hs.Save("swap", "", 100) } else { hs.Save("swap", "", float64(100*(u/t))) } } return nil }