1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
// SPDX-License-Identifier: BSD-3-Clause
//go:build solaris
package host
import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
"os"
"regexp"
"strconv"
"strings"
"github.com/shirou/gopsutil/v4/internal/common"
)
func HostIDWithContext(ctx context.Context) (string, error) {
platform, err := parseReleaseFile()
if err != nil {
return "", err
}
if platform == "SmartOS" {
// If everything works, use the current zone ID as the HostID if present.
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" {
return strings.TrimSpace(line), nil
}
hostname, err := os.Hostname()
if err == nil {
return hostname, nil
}
}
}
}
// If HostID is still unknown, 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.
out, err := invoke.CommandWithContext(ctx, "hostid")
if err == nil {
sc := bufio.NewScanner(bytes.NewReader(out))
for sc.Scan() {
line := sc.Text()
return strings.TrimSpace(line), nil
}
}
return "", nil
}
// Count number of processes based on the number of entries in /proc
func numProcs(ctx context.Context) (uint64, error) {
dirs, err := os.ReadDir("/proc")
if err != nil {
return 0, err
}
return uint64(len(dirs)), nil
}
var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`)
func BootTimeWithContext(ctx context.Context) (uint64, error) {
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 UptimeWithContext(ctx context.Context) (uint64, error) {
bootTime, err := BootTime() //nolint:contextcheck //FIXME
if err != nil {
return 0, err
}
return timeSince(bootTime), nil
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
return []UserStat{}, common.ErrNotImplementedError
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
// Find distribution name from /etc/release
func parseReleaseFile() (string, error) {
b, err := os.ReadFile("/etc/release")
if err != nil {
return "", err
}
s := string(b)
s = strings.TrimSpace(s)
var platform string
switch {
case strings.HasPrefix(s, "SmartOS"):
platform = "SmartOS"
case strings.HasPrefix(s, "OpenIndiana"):
platform = "OpenIndiana"
case strings.HasPrefix(s, "OmniOS"):
platform = "OmniOS"
case strings.HasPrefix(s, "Open Storage"):
platform = "NexentaStor"
case strings.HasPrefix(s, "Solaris"):
platform = "Solaris"
case strings.HasPrefix(s, "Oracle Solaris"):
platform = "Solaris"
default:
platform = strings.Fields(s)[0]
}
return platform, nil
}
// parseUnameOutput returns platformFamily, kernelVersion and platformVersion
func parseUnameOutput(ctx context.Context) (string, string, string, error) {
out, err := invoke.CommandWithContext(ctx, "uname", "-srv")
if err != nil {
return "", "", "", err
}
fields := strings.Fields(string(out))
if len(fields) < 3 {
return "", "", "", errors.New("malformed `uname` output")
}
return fields[0], fields[1], fields[2], nil
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
_, kernelVersion, _, err := parseUnameOutput(ctx)
return kernelVersion, err
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
platform, err := parseReleaseFile()
if err != nil {
return "", "", "", err
}
platformFamily, _, platformVersion, err := parseUnameOutput(ctx)
if err != nil {
return "", "", "", err
}
return platform, platformFamily, platformVersion, nil
}
|