1
0
mirror of https://github.com/shirou/gopsutil.git synced 2025-04-26 13:48:59 +08:00
shirou_gopsutil/host_linux.go

345 lines
7.3 KiB
Go
Raw Normal View History

2014-05-14 00:12:17 +09:00
// +build linux
2014-04-18 21:28:00 +09:00
2014-04-22 09:44:22 +09:00
package gopsutil
2014-04-18 21:28:00 +09:00
import (
2014-04-22 17:38:47 +09:00
"bytes"
2014-04-22 17:39:51 +09:00
"encoding/binary"
2014-04-22 17:38:47 +09:00
"io/ioutil"
2014-04-18 21:28:00 +09:00
"os"
"os/exec"
"runtime"
2014-05-16 18:11:17 +09:00
"strings"
2014-04-18 21:28:00 +09:00
"syscall"
2014-04-22 17:38:47 +09:00
"unsafe"
2014-04-18 21:28:00 +09:00
)
type LSB struct {
ID string
Release string
Codename string
Description string
}
func HostInfo() (*HostInfoStat, error) {
2014-04-18 21:28:00 +09:00
hostname, err := os.Hostname()
2014-04-22 09:48:48 +09:00
if err != nil {
return nil, err
2014-04-22 09:48:48 +09:00
}
ret := &HostInfoStat{
Hostname: hostname,
OS: runtime.GOOS,
}
platform, family, version, err := GetPlatformInformation()
2014-05-16 18:11:17 +09:00
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
}
system, role, err := GetVirtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
2014-05-18 23:45:54 +09:00
uptime, err := BootTime()
if err == nil {
ret.Uptime = uptime
}
return ret, nil
}
2014-05-18 23:45:54 +09:00
func BootTime() (uint64, error) {
2014-04-22 09:48:48 +09:00
sysinfo := &syscall.Sysinfo_t{}
if err := syscall.Sysinfo(sysinfo); err != nil {
return 0, err
2014-04-22 09:48:48 +09:00
}
2014-05-18 23:43:44 +09:00
return uint64(sysinfo.Uptime), nil
2014-04-18 21:28:00 +09:00
}
2014-04-22 17:38:47 +09:00
func Users() ([]UserStat, error) {
utmpfile := "/var/run/utmp"
file, err := os.Open(utmpfile)
if err != nil {
2014-05-01 12:47:43 +09:00
return nil, err
2014-04-22 17:38:47 +09:00
}
buf, err := ioutil.ReadAll(file)
if err != nil {
2014-05-01 12:47:43 +09:00
return nil, err
2014-04-22 17:38:47 +09:00
}
u := utmp{}
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize
2014-05-01 12:47:43 +09:00
ret := make([]UserStat, 0, count)
2014-04-22 17:38:47 +09:00
for i := 0; i < count; i++ {
b := buf[i*entrySize : i*entrySize+entrySize]
2014-04-22 17:39:51 +09:00
var u utmp
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
2014-04-22 17:38:47 +09:00
if err != nil {
continue
}
user := UserStat{
2014-04-30 16:16:07 +09:00
User: byteToString(u.UtUser[:]),
Terminal: byteToString(u.UtLine[:]),
Host: byteToString(u.UtHost[:]),
Started: int(u.UtTv.TvSec),
2014-04-22 17:38:47 +09:00
}
ret = append(ret, user)
}
return ret, nil
}
func getLSB() (*LSB, error) {
ret := &LSB{}
if pathExists("/etc/lsb-release") {
contents, err := readLines("/etc/lsb-release")
if err != nil {
return ret, err // return empty
}
for _, line := range contents {
field := strings.Split(line, "=")
if len(field) < 2 {
continue
}
switch field[0] {
case "DISTRIB_ID":
ret.ID = field[1]
case "DISTRIB_RELEASE":
ret.Release = field[1]
case "DISTRIB_CODENAME":
ret.Codename = field[1]
case "DISTRIB_DESCRIPTION":
ret.Description = field[1]
}
}
} else if pathExists("/usr/bin/lsb_release") {
out, err := exec.Command("/usr/bin/lsb_release").Output()
if err != nil {
return ret, err
}
for _, line := range strings.Split(string(out), "\n") {
field := strings.Split(line, ":")
if len(field) < 2 {
continue
}
switch field[0] {
case "Distributor ID":
ret.ID = field[1]
case "Release":
ret.Release = field[1]
case "Codename":
ret.Codename = field[1]
case "Description":
ret.Description = field[1]
}
}
}
return ret, nil
}
func GetPlatformInformation() (string, string, string, error) {
platform := ""
family := ""
version := ""
lsb, _ := getLSB()
if pathExists("/etc/oracle-release") {
platform = "oracle"
contents, err := readLines("/etc/oracle-release")
if err == nil {
version, _ = getRedhatishVersion(contents)
}
} else if pathExists("/etc/enterprise-release") {
platform = "oracle"
contents, err := readLines("/etc/enterprise-release")
if err == nil {
version, _ = getRedhatishVersion(contents)
}
} else if pathExists("/etc/debian_version") {
2014-05-16 18:11:17 +09:00
if lsb.ID == "Ubuntu" {
platform = "ubuntu"
version = lsb.Release
} else if lsb.ID == "LinuxMint" {
platform = "linuxmint"
version = lsb.Release
} else {
if pathExists("/usr/bin/raspi-config") {
platform = "raspbian"
} else {
platform = "debian"
}
contents, err := readLines("/etc/debian_version")
if err == nil {
version = contents[0]
}
}
2014-05-16 18:11:17 +09:00
} else if pathExists("/etc/redhat-release") {
contents, err := readLines("/etc/redhat-release")
if err == nil {
version, _ = getRedhatishVersion(contents)
platform, _ = getRedhatishPlatform(contents)
}
2014-05-16 18:11:17 +09:00
} else if pathExists("/etc/system-release") {
contents, err := readLines("/etc/system-release")
if err == nil {
version, _ = getRedhatishVersion(contents)
platform, _ = getRedhatishPlatform(contents)
}
2014-05-16 18:11:17 +09:00
} else if pathExists("/etc/gentoo-release") {
platform = "gentoo"
contents, err := readLines("/etc/gentoo-release")
if err == nil {
version, _ = getRedhatishVersion(contents)
}
// TODO: suse detection
// TODO: slackware detecion
2014-05-16 18:11:17 +09:00
} else if pathExists("/etc/arch-release") {
platform = "arch"
// TODO: exherbo detection
2014-05-16 18:11:17 +09:00
} else if lsb.ID == "RedHat" {
platform = "redhat"
version = lsb.Release
2014-05-16 18:11:17 +09:00
} else if lsb.ID == "Amazon" {
platform = "amazon"
2014-05-16 18:11:17 +09:00
version = lsb.Release
} else if lsb.ID == "ScientificSL" {
platform = "scientific"
2014-05-16 18:11:17 +09:00
version = lsb.Release
} else if lsb.ID == "XenServer" {
platform = "xenserver"
2014-05-16 18:11:17 +09:00
version = lsb.Release
} else if lsb.ID != "" {
platform = strings.ToLower(lsb.ID)
version = lsb.Release
}
switch platform {
case "debian", "ubuntu", "linuxmint", "raspbian":
family = "debian"
case "fedora":
family = "fedora"
case "oracle", "centos", "redhat", "scientific", "enterpriseenterprise", "amazon", "xenserver", "cloudlinux", "ibm_powerkvm":
family = "rhel"
case "suse":
family = "suse"
case "gentoo":
family = "gentoo"
case "slackware":
family = "slackware"
case "arch":
family = "arch"
case "exherbo":
family = "exherbo"
}
return platform, family, version, nil
}
func getRedhatishVersion(contents []string) (string, error) {
return "", nil
}
func getRedhatishPlatform(contents []string) (string, error) {
return "", nil
}
func GetVirtualization() (string, string, error) {
var system string
var role string
if pathExists("/proc/xen") {
system = "xen"
role = "guest" // assume guest
if pathExists("/proc/xen/capabilities") {
contents, err := readLines("/proc/xen/capabilities")
if err == nil {
if stringContains(contents, "control_d") {
role = "host"
}
}
}
}
if pathExists("/proc/modules") {
contents, err := readLines("/proc/modules")
if err == nil {
if stringContains(contents, "kvm") {
system = "kvm"
role = "host"
} else if stringContains(contents, "vboxdrv") {
system = "vbox"
role = "host"
} else if stringContains(contents, "vboxguest") {
system = "vbox"
role = "guest"
}
}
}
if pathExists("/proc/cpuinfo") {
contents, err := readLines("/proc/cpuinfo")
if err == nil {
if stringContains(contents, "QEMU Virtual CPU") ||
stringContains(contents, "Common KVM processor") ||
stringContains(contents, "Common 32-bit KVM processor") {
system = "kvm"
role = "guest"
}
}
}
if pathExists("/proc/bc/0") {
system = "openvz"
role = "host"
} else if pathExists("/proc/vz") {
system = "openvz"
role = "guest"
}
// not use dmidecode because it requires root
if pathExists("/proc/self/status") {
contents, err := readLines("/proc/self/status")
if err == nil {
if stringContains(contents, "s_context:") ||
stringContains(contents, "VxID:") {
system = "linux-vserver"
}
// TODO: guest or host
}
}
if pathExists("/proc/self/cgroup") {
contents, err := readLines("/proc/self/cgroup")
if err == nil {
if stringContains(contents, "lxc") ||
stringContains(contents, "docker") {
system = "lxc"
role = "guest"
} else if pathExists("/usr/bin/lxc-version") { // TODO: which
system = "lxc"
role = "host"
}
}
}
return system, role, nil
}