251 lines
5.3 KiB
Go
251 lines
5.3 KiB
Go
// +build linux
|
|
|
|
package gopsutil
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"runtime"
|
|
"strings"
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
type LSB struct {
|
|
ID string
|
|
Release string
|
|
Codename string
|
|
Description string
|
|
}
|
|
|
|
func HostInfo() (*HostInfoStat, error) {
|
|
hostname, err := os.Hostname()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ret := &HostInfoStat{
|
|
Hostname: hostname,
|
|
OS: runtime.GOOS,
|
|
}
|
|
|
|
platform, family, version, err := getPlatformInformation()
|
|
if err == nil {
|
|
ret.Platform = platform
|
|
ret.PlatformFamily = family
|
|
ret.PlatformVersion = version
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func BootTime() (int64, error) {
|
|
sysinfo := &syscall.Sysinfo_t{}
|
|
if err := syscall.Sysinfo(sysinfo); err != nil {
|
|
return 0, err
|
|
}
|
|
return int64(sysinfo.Uptime), nil
|
|
}
|
|
|
|
func Users() ([]UserStat, error) {
|
|
utmpfile := "/var/run/utmp"
|
|
|
|
file, err := os.Open(utmpfile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
buf, err := ioutil.ReadAll(file)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
u := utmp{}
|
|
entrySize := int(unsafe.Sizeof(u))
|
|
count := len(buf) / entrySize
|
|
|
|
ret := make([]UserStat, 0, count)
|
|
|
|
for i := 0; i < count; i++ {
|
|
b := buf[i*entrySize : i*entrySize+entrySize]
|
|
|
|
var u utmp
|
|
br := bytes.NewReader(b)
|
|
err := binary.Read(br, binary.LittleEndian, &u)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
user := UserStat{
|
|
User: byteToString(u.UtUser[:]),
|
|
Terminal: byteToString(u.UtLine[:]),
|
|
Host: byteToString(u.UtHost[:]),
|
|
Started: int(u.UtTv.TvSec),
|
|
}
|
|
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") {
|
|
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]
|
|
}
|
|
}
|
|
} else if pathExists("/etc/redhat-release") {
|
|
contents, err := readLines("/etc/redhat-release")
|
|
if err == nil {
|
|
version, _ = getRedhatishVersion(contents)
|
|
platform, _ = getRedhatishPlatform(contents)
|
|
}
|
|
} else if pathExists("/etc/system-release") {
|
|
contents, err := readLines("/etc/system-release")
|
|
if err == nil {
|
|
version, _ = getRedhatishVersion(contents)
|
|
platform, _ = getRedhatishPlatform(contents)
|
|
}
|
|
} 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
|
|
} else if pathExists("/etc/arch-release") {
|
|
platform = "arch"
|
|
// TODO: exherbo detection
|
|
} else if lsb.ID == "RedHat" {
|
|
platform = "redhat"
|
|
version = lsb.Release
|
|
} else if lsb.ID == "Amazon" {
|
|
platform = "amazon"
|
|
version = lsb.Release
|
|
} else if lsb.ID == "ScientificSL" {
|
|
platform = "scientific"
|
|
version = lsb.Release
|
|
} else if lsb.ID == "XenServer" {
|
|
platform = "xenserver"
|
|
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
|
|
}
|