@@ -21,17 +21,54 @@ package util
21
21
22
22
import (
23
23
"fmt"
24
+ "os"
25
+ "strconv"
26
+ "strings"
24
27
"time"
25
28
26
29
"golang.org/x/sys/unix"
30
+ "k8s.io/klog/v2"
27
31
)
28
32
29
- // GetBootTime returns the time at which the machine was started, truncated to the nearest second
33
+ // GetBootTime returns the time at which the machine was started, truncated to the nearest second.
34
+ // It uses /proc/stat first, which is more accurate, and falls back to the less accurate
35
+ // unix.Sysinfo if /proc/stat failed.
30
36
func GetBootTime () (time.Time , error ) {
37
+ bootTime , err := getBootTimeWithProcStat ()
38
+ if err != nil {
39
+ klog .InfoS ("Failed to get boot time from /proc/uptime. Will retry with unix.Sysinfo." , "error" , err )
40
+ return getBootTimeWithSysinfo ()
41
+ }
42
+ return bootTime , nil
43
+ }
44
+
45
+ func getBootTimeWithProcStat () (time.Time , error ) {
46
+ raw , err := os .ReadFile ("/proc/stat" )
47
+ if err != nil {
48
+ return time.Time {}, fmt .Errorf ("error getting boot time: %w" , err )
49
+ }
50
+ rawFields := strings .Fields (string (raw ))
51
+ for i , v := range rawFields {
52
+ if v == "btime" {
53
+ if len (rawFields ) > i + 1 {
54
+ sec , err := strconv .ParseInt (rawFields [i + 1 ], 10 , 64 )
55
+ if err != nil {
56
+ return time.Time {}, fmt .Errorf ("error parsing boot time %s: %w" , rawFields [i + 1 ], err )
57
+ }
58
+ return time .Unix (sec , 0 ), nil
59
+ }
60
+ break
61
+ }
62
+ }
63
+
64
+ return time.Time {}, fmt .Errorf ("can not find btime from /proc/stat: %s" , raw )
65
+ }
66
+
67
+ func getBootTimeWithSysinfo () (time.Time , error ) {
31
68
currentTime := time .Now ()
32
69
var info unix.Sysinfo_t
33
70
if err := unix .Sysinfo (& info ); err != nil {
34
- return time.Time {}, fmt .Errorf ("error getting system uptime: %s " , err )
71
+ return time.Time {}, fmt .Errorf ("error getting system uptime: %w " , err )
35
72
}
36
73
return currentTime .Add (- time .Duration (info .Uptime ) * time .Second ).Truncate (time .Second ), nil
37
74
}
0 commit comments