package netmgrd import ( "fmt" "math" "os/exec" "sync" "time" "github.com/beevik/ntp" "golang.org/x/sys/unix" ) var servers = []string{ "210.72.145.44", "ntp.aliyun.com", "ntp.ntsc.ac.cn", } type ntpResult struct { t time.Time d time.Duration err error } func SyncNTPTime() error { t, err := getAccurateTime(servers, 5*time.Second) if err != nil { return err } if err := SetSystemTime(t); err != nil { return err } return nil } func getAccurateTime(servers []string, timeout time.Duration) (time.Time, error) { ch := make(chan ntpResult, len(servers)) var wg sync.WaitGroup wg.Add(len(servers)) for _, s := range servers { go func(s string) { defer wg.Done() resp, err := ntp.QueryWithOptions(s, ntp.QueryOptions{Timeout: timeout}) if err != nil { ch <- ntpResult{err: err} return } if resp.Stratum == 0 || resp.Time.IsZero() { ch <- ntpResult{err: fmt.Errorf("invalid ntp response")} return } t := resp.Time.Add(resp.RTT / 2) d := resp.RootDistance // 最大可能偏差 ch <- ntpResult{t: t, d: d, err: nil} }(s) } go func() { wg.Wait() close(ch) }() var bestTime time.Time var bestDist time.Duration = math.MaxInt64 for r := range ch { if r.err != nil { continue } if r.d < bestDist { bestDist = r.d bestTime = r.t } } if bestTime.IsZero() { return time.Time{}, fmt.Errorf("no valid ntp response") } return bestTime, nil } var setTimeMu sync.Mutex // 调用SetSystemTime()函数的并发互斥 func SetSystemTime(t time.Time) error { setTimeMu.Lock() defer setTimeMu.Unlock() ts := unix.NsecToTimespec(t.UnixNano()) if err := unix.ClockSettime(unix.CLOCK_REALTIME, &ts); err != nil { return err } _ = exec.Command("hwclock", "-w").Run() return nil }