package netmgrd import ( "fmt" "math" "os/exec" "sync" "time" "github.com/beevik/ntp" ) 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() cmd := exec.Command("date", "-s", t.Local().Format("2006-01-02 15:04:05")) output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("%v, output: %s", err, string(output)) } return nil }