| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- 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
- }
|