@ -15,7 +15,6 @@ import (
"runtime"
"strconv"
"strings"
"sync/atomic"
"time"
"github.com/shirou/gopsutil/internal/common"
@ -105,71 +104,13 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
return ret , nil
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
// BootTime returns the system boot time expressed in seconds since the epoch.
func BootTime ( ) ( uint64 , error ) {
return BootTimeWithContext ( context . Background ( ) )
}
func BootTimeWithContext ( ctx context . Context ) ( uint64 , error ) {
t := atomic . LoadUint64 ( & cachedBootTime )
if t != 0 {
return t , nil
}
system , role , err := Virtualization ( )
if err != nil {
return 0 , err
}
statFile := "stat"
if system == "lxc" && role == "guest" {
// if lxc, /proc/uptime is used.
statFile = "uptime"
} else if system == "docker" && role == "guest" {
// also docker, guest
statFile = "uptime"
}
filename := common . HostProc ( statFile )
lines , err := common . ReadLines ( filename )
if err != nil {
return 0 , err
}
if statFile == "stat" {
for _ , line := range lines {
if strings . HasPrefix ( line , "btime" ) {
f := strings . Fields ( line )
if len ( f ) != 2 {
return 0 , fmt . Errorf ( "wrong btime format" )
}
b , err := strconv . ParseInt ( f [ 1 ] , 10 , 64 )
if err != nil {
return 0 , err
}
t = uint64 ( b )
atomic . StoreUint64 ( & cachedBootTime , t )
return t , nil
}
}
} else if statFile == "uptime" {
if len ( lines ) != 1 {
return 0 , fmt . Errorf ( "wrong uptime format" )
}
f := strings . Fields ( lines [ 0 ] )
b , err := strconv . ParseFloat ( f [ 0 ] , 64 )
if err != nil {
return 0 , err
}
t = uint64 ( time . Now ( ) . Unix ( ) ) - uint64 ( b )
atomic . StoreUint64 ( & cachedBootTime , t )
return t , nil
}
return 0 , fmt . Errorf ( "could not find btime" )
return common . BootTimeWithContext ( ctx )
}
func uptime ( boot uint64 ) uint64 {
@ -235,26 +176,6 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
}
func getOSRelease ( ) ( platform string , version string , err error ) {
contents , err := common . ReadLines ( common . HostEtc ( "os-release" ) )
if err != nil {
return "" , "" , nil // return empty
}
for _ , line := range contents {
field := strings . Split ( line , "=" )
if len ( field ) < 2 {
continue
}
switch field [ 0 ] {
case "ID" : // use ID for lowercase
platform = field [ 1 ]
case "VERSION" :
version = field [ 1 ]
}
}
return platform , version , nil
}
func getLSB ( ) ( * LSB , error ) {
ret := & LSB { }
if common . PathExists ( common . HostEtc ( "lsb-release" ) ) {
@ -392,7 +313,7 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
version = contents [ 0 ]
}
} else if common . PathExists ( common . HostEtc ( "os-release" ) ) {
p , v , err := g etOSRelease( )
p , v , err := common . G etOSRelease( )
if err == nil {
platform = p
version = v
@ -515,106 +436,7 @@ func Virtualization() (string, string, error) {
}
func VirtualizationWithContext ( ctx context . Context ) ( string , string , error ) {
var system string
var role string
filename := common . HostProc ( "xen" )
if common . PathExists ( filename ) {
system = "xen"
role = "guest" // assume guest
if common . PathExists ( filepath . Join ( filename , "capabilities" ) ) {
contents , err := common . ReadLines ( filepath . Join ( filename , "capabilities" ) )
if err == nil {
if common . StringsContains ( contents , "control_d" ) {
role = "host"
}
}
}
}
filename = common . HostProc ( "modules" )
if common . PathExists ( filename ) {
contents , err := common . ReadLines ( filename )
if err == nil {
if common . StringsContains ( contents , "kvm" ) {
system = "kvm"
role = "host"
} else if common . StringsContains ( contents , "vboxdrv" ) {
system = "vbox"
role = "host"
} else if common . StringsContains ( contents , "vboxguest" ) {
system = "vbox"
role = "guest"
} else if common . StringsContains ( contents , "vmware" ) {
system = "vmware"
role = "guest"
}
}
}
filename = common . HostProc ( "cpuinfo" )
if common . PathExists ( filename ) {
contents , err := common . ReadLines ( filename )
if err == nil {
if common . StringsContains ( contents , "QEMU Virtual CPU" ) ||
common . StringsContains ( contents , "Common KVM processor" ) ||
common . StringsContains ( contents , "Common 32-bit KVM processor" ) {
system = "kvm"
role = "guest"
}
}
}
filename = common . HostProc ( )
if common . PathExists ( filepath . Join ( filename , "bc" , "0" ) ) {
system = "openvz"
role = "host"
} else if common . PathExists ( filepath . Join ( filename , "vz" ) ) {
system = "openvz"
role = "guest"
}
// not use dmidecode because it requires root
if common . PathExists ( filepath . Join ( filename , "self" , "status" ) ) {
contents , err := common . ReadLines ( filepath . Join ( filename , "self" , "status" ) )
if err == nil {
if common . StringsContains ( contents , "s_context:" ) ||
common . StringsContains ( contents , "VxID:" ) {
system = "linux-vserver"
}
// TODO: guest or host
}
}
if common . PathExists ( filepath . Join ( filename , "self" , "cgroup" ) ) {
contents , err := common . ReadLines ( filepath . Join ( filename , "self" , "cgroup" ) )
if err == nil {
if common . StringsContains ( contents , "lxc" ) {
system = "lxc"
role = "guest"
} else if common . StringsContains ( contents , "docker" ) {
system = "docker"
role = "guest"
} else if common . StringsContains ( contents , "machine-rkt" ) {
system = "rkt"
role = "guest"
} else if common . PathExists ( "/usr/bin/lxc-version" ) {
system = "lxc"
role = "host"
}
}
}
if common . PathExists ( common . HostEtc ( "os-release" ) ) {
p , _ , err := getOSRelease ( )
if err == nil && p == "coreos" {
system = "rkt" // Is it true?
role = "host"
}
}
return system , role , nil
return common . VirtualizationWithContext ( ctx )
}
func SensorsTemperatures ( ) ( [ ] TemperatureStat , error ) {