| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- package netmgrd
- import (
- "fmt"
- "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
- stratum uint8
- 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 || resp.Stratum == 0 || resp.Stratum > 5 || resp.Time.IsZero() {
- ch <- ntpResult{err: err} // "resp.Stratum"为0(无效服务器)或大于5(精度较低)
- return
- }
- ch <- ntpResult{t: resp.Time, stratum: resp.Stratum}
- }(s)
- }
- go func() {
- wg.Wait()
- close(ch)
- }()
- var results []ntpResult
- for r := range ch {
- if r.err == nil {
- results = append(results, r)
- }
- }
- if len(results) == 0 {
- return time.Time{}, fmt.Errorf("所有NTP服务器请求失败或无有效时间")
- }
- // 找最低 Stratum
- minStratum := uint8(255)
- for _, r := range results {
- if r.stratum < minStratum {
- minStratum = r.stratum
- }
- }
- // 最低 Stratum 的时间
- var bestTimes []time.Time
- for _, r := range results {
- if r.stratum == minStratum {
- bestTimes = append(bestTimes, r.t)
- }
- }
- return bestTimes[0], 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
- }
|