123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- package host
- import (
- "bufio"
- "bytes"
- "context"
- "fmt"
- "io/ioutil"
- "os"
- "os/exec"
- "regexp"
- "runtime"
- "strconv"
- "strings"
- "time"
- "github.com/shirou/gopsutil/internal/common"
- )
- func Info() (*InfoStat, error) {
- return InfoWithContext(context.Background())
- }
- func InfoWithContext(ctx context.Context) (*InfoStat, error) {
- result := &InfoStat{
- OS: runtime.GOOS,
- }
- hostname, err := os.Hostname()
- if err != nil {
- return nil, err
- }
- result.Hostname = hostname
- // Parse versions from output of `uname(1)`
- uname, err := exec.LookPath("/usr/bin/uname")
- if err != nil {
- return nil, err
- }
- out, err := invoke.CommandWithContext(ctx, uname, "-srv")
- if err != nil {
- return nil, err
- }
- fields := strings.Fields(string(out))
- if len(fields) >= 1 {
- result.PlatformFamily = fields[0]
- }
- if len(fields) >= 2 {
- result.KernelVersion = fields[1]
- }
- if len(fields) == 3 {
- result.PlatformVersion = fields[2]
- }
- // Find distribution name from /etc/release
- fh, err := os.Open("/etc/release")
- if err != nil {
- return nil, err
- }
- defer fh.Close()
- sc := bufio.NewScanner(fh)
- if sc.Scan() {
- line := strings.TrimSpace(sc.Text())
- switch {
- case strings.HasPrefix(line, "SmartOS"):
- result.Platform = "SmartOS"
- case strings.HasPrefix(line, "OpenIndiana"):
- result.Platform = "OpenIndiana"
- case strings.HasPrefix(line, "OmniOS"):
- result.Platform = "OmniOS"
- case strings.HasPrefix(line, "Open Storage"):
- result.Platform = "NexentaStor"
- case strings.HasPrefix(line, "Solaris"):
- result.Platform = "Solaris"
- case strings.HasPrefix(line, "Oracle Solaris"):
- result.Platform = "Solaris"
- default:
- result.Platform = strings.Fields(line)[0]
- }
- }
- switch result.Platform {
- case "SmartOS":
- // If everything works, use the current zone ID as the HostID if present.
- zonename, err := exec.LookPath("/usr/bin/zonename")
- if err == nil {
- out, err := invoke.CommandWithContext(ctx, zonename)
- if err == nil {
- sc := bufio.NewScanner(bytes.NewReader(out))
- for sc.Scan() {
- line := sc.Text()
- // If we're in the global zone, rely on the hostname.
- if line == "global" {
- hostname, err := os.Hostname()
- if err == nil {
- result.HostID = hostname
- }
- } else {
- result.HostID = strings.TrimSpace(line)
- break
- }
- }
- }
- }
- }
- // If HostID is still empty, use hostid(1), which can lie to callers but at
- // this point there are no hardware facilities available. This behavior
- // matches that of other supported OSes.
- if result.HostID == "" {
- hostID, err := exec.LookPath("/usr/bin/hostid")
- if err == nil {
- out, err := invoke.CommandWithContext(ctx, hostID)
- if err == nil {
- sc := bufio.NewScanner(bytes.NewReader(out))
- for sc.Scan() {
- line := sc.Text()
- result.HostID = strings.TrimSpace(line)
- break
- }
- }
- }
- }
- // Find the boot time and calculate uptime relative to it
- bootTime, err := BootTime()
- if err != nil {
- return nil, err
- }
- result.BootTime = bootTime
- result.Uptime = uptimeSince(bootTime)
- // Count number of processes based on the number of entries in /proc
- dirs, err := ioutil.ReadDir("/proc")
- if err != nil {
- return nil, err
- }
- result.Procs = uint64(len(dirs))
- return result, nil
- }
- var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`)
- func BootTime() (uint64, error) {
- return BootTimeWithContext(context.Background())
- }
- func BootTimeWithContext(ctx context.Context) (uint64, error) {
- kstat, err := exec.LookPath("/usr/bin/kstat")
- if err != nil {
- return 0, err
- }
- out, err := invoke.CommandWithContext(ctx, kstat, "-p", "unix:0:system_misc:boot_time")
- if err != nil {
- return 0, err
- }
- kstats := kstatMatch.FindAllStringSubmatch(string(out), -1)
- if len(kstats) != 1 {
- return 0, fmt.Errorf("expected 1 kstat, found %d", len(kstats))
- }
- return strconv.ParseUint(kstats[0][2], 10, 64)
- }
- func Uptime() (uint64, error) {
- return UptimeWithContext(context.Background())
- }
- func UptimeWithContext(ctx context.Context) (uint64, error) {
- bootTime, err := BootTime()
- if err != nil {
- return 0, err
- }
- return uptimeSince(bootTime), nil
- }
- func uptimeSince(since uint64) uint64 {
- return uint64(time.Now().Unix()) - since
- }
- func Users() ([]UserStat, error) {
- return UsersWithContext(context.Background())
- }
- func UsersWithContext(ctx context.Context) ([]UserStat, error) {
- return []UserStat{}, common.ErrNotImplementedError
- }
- func SensorsTemperatures() ([]TemperatureStat, error) {
- return SensorsTemperaturesWithContext(context.Background())
- }
- func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
- return []TemperatureStat{}, common.ErrNotImplementedError
- }
- func Virtualization() (string, string, error) {
- return VirtualizationWithContext(context.Background())
- }
- func VirtualizationWithContext(ctx context.Context) (string, string, error) {
- return "", "", common.ErrNotImplementedError
- }
- func KernelVersion() (string, error) {
- return KernelVersionWithContext(context.Background())
- }
- func KernelVersionWithContext(ctx context.Context) (string, error) {
- // Parse versions from output of `uname(1)`
- uname, err := exec.LookPath("/usr/bin/uname")
- if err != nil {
- return "", err
- }
- out, err := invoke.CommandWithContext(ctx, uname, "-srv")
- if err != nil {
- return "", err
- }
- fields := strings.Fields(string(out))
- if len(fields) >= 2 {
- return fields[1], nil
- }
- return "", fmt.Errorf("could not get kernel version")
- }
- func PlatformInformation() (platform string, family string, version string, err error) {
- return PlatformInformationWithContext(context.Background())
- }
- func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
- /* This is not finished yet at all. Please contribute! */
- version, err = KernelVersion()
- if err != nil {
- return "", "", "", err
- }
- return "solaris", "solaris", version, nil
- }
|