LiuShen

LiuShen / 通过HTTP同步时间

Last active 6 hours ago

Like 0

在123端口无法使用的情况下通过http请求头携带的时间实现时间同步

sync-time.sh Raw
1#!/bin/bash
2
3set -e
4
5URL="http://www.baidu.com/"
6COUNT=10
7
8echo "正在通过百度 HTTP 校准系统时间..."
9echo
10
11best_rtt=999999999
12best_time=0
13
14for i in $(seq 1 "$COUNT"); do
15 start=$(date +%s%3N)
16
17 headers=$(curl \
18 --noproxy '*' \
19 --connect-timeout 3 \
20 --max-time 5 \
21 -sS \
22 -D - \
23 -o /dev/null \
24 "$URL" 2>/dev/null) || {
25 echo "[$i/$COUNT] 请求失败"
26 continue
27 }
28
29 end=$(date +%s%3N)
30
31 date_header=$(printf '%s\n' "$headers" |
32 grep -i '^Date:' |
33 tail -n 1 |
34 sed 's/^[Dd]ate:[[:space:]]*//')
35
36 if [ -z "$date_header" ]; then
37 echo "[$i/$COUNT] 未找到 Date 头"
38 continue
39 fi
40
41 server_sec=$(date -u -d "$date_header" +%s 2>/dev/null) || {
42 echo "[$i/$COUNT] 无法解析 Date: $date_header"
43 continue
44 }
45
46 rtt=$((end - start))
47 half_rtt=$((rtt / 2))
48
49 # Date 头的时间 + 请求往返时间的一半
50 estimated_ms=$((server_sec * 1000 + half_rtt))
51
52 echo "[$i/$COUNT] RTT=${rtt}ms Date=$date_header"
53
54 if [ "$rtt" -lt "$best_rtt" ]; then
55 best_rtt=$rtt
56 best_time=$estimated_ms
57 fi
58done
59
60if [ "$best_time" -eq 0 ]; then
61 echo
62 echo "错误:无法从百度获取时间"
63 exit 1
64fi
65
66echo
67echo "最佳 RTT: ${best_rtt}ms"
68
69before=$(date '+%Y-%m-%d %H:%M:%S.%3N')
70
71# 设置系统时间
72date -u -s "@$(awk "BEGIN {printf \"%.3f\", $best_time / 1000}")" >/dev/null
73
74after=$(date '+%Y-%m-%d %H:%M:%S.%3N')
75
76echo "校时前: $before"
77echo "校时后: $after"
78echo "校时完成。"