summaryrefslogtreecommitdiffstats
path: root/satellit_installer/static_files/timesync/usr/local/sbin/redneck-timesync.sh
blob: 33cab2afbf9285e9a348bae80256cdbf49dd1953 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/bin/sh

USR=$(id -u)
if [ "$USR" != 0 ]; then
	echo "Not running as root"
	exit 1
fi

DRYRUN=true
BOOTUP=false
while [ "$#" -gt 0 ]; do
	case "$1" in
	-s)
		DRYRUN=false
		;;
	-b)
		BOOTUP=true
	esac
done

if $BOOTUP; then
	MIN_DIFF=7
	MAX_DIFF=86400
else
	# Not bootup mode, ntpd present, ntpq yields no error:
	# Assume ntpd is up and running, so don't do anything
	command -v ntpd > /dev/null && ntpq -p > /dev/null 2>&1 && exit 0
	# Same for systemd timesync
	systemctl -q is-active systemd-timesyncd && exit 0
	# No other timesync, go
	MIN_DIFF=4
	MAX_DIFF=300
fi


# Check if clock is set properly by probing a bunch of web servers for
# their current time. Then -- after applying some sanity checks -- pick
# the median of the results and set the local clock to that time
# if the difference to our local clock is at least one minute and
# at most one day (limits adjustable below)
# This can be pretty useful in constrained environments with no
# real time servers accessible.

$BOOTUP && /usr/local/sbin/slx-wait-online

URLS="
	https://www.uni-freiburg.de
	https://www.bwlehrpool.de
	https://bwlp-masterserver.ruf.uni-freiburg.de
	https://www.dfn.de
	https://www.switch.ch
	https://www.debian.org
	https://kernel.org
"

F=$(mktemp)
[ -z "$F" ] && F="/tmp/timesync-boot.$$"
NOW=$(date +%s)
ECODE=0

# Request all at once, HEAD only, 2 sec timeout
for url in $URLS; do
	curl -s -m 2 -I "$url" &
done | grep -i ^Date: | cut -c7- | while read -r line || [ -n "$line" ]; do
	# convert each one to unix timestamp
	T=$(date -d "$line" +%s)
	# sanity check
	[ -n "$T" ] && [ "$T" -gt 1234567890 ] && echo "$T"
done | sort -n > "$F"

# Get the median of the sorted values
COUNT=$(wc -l "$F")
COUNT=${COUNT%% *}
if [ "$COUNT" -ge 3 ]; then
	CENTER=$(( COUNT / 2 + 1 ))
	BEST=$( head -n "$CENTER" "$F" | tail -n 1 )
	if [ "$BEST" -gt "$NOW" ]; then
		DIFF=$(( BEST - NOW ))
	else
		DIFF=$(( NOW - BEST ))
	fi
	if [ "$DIFF" -gt "$MAX_DIFF" ]; then
		echo "Clock difference too large (${DIFF} seconds); refusing to fix."
		ECODE=1
	elif [ "$DIFF" -lt "$MIN_DIFF" ]; then
		echo "Clock difference ${DIFF}, ok (within ${MIN_DIFF} seconds)"
	elif "$DRYRUN"; then
		echo "Clock difference is ${DIFF}, but -s is not passed, not correcting time."
	else
		echo "Clock difference is ${DIFF} seconds, setting..."
		date -s "@$BEST"
	fi
else
	echo "Not enough time probes ($COUNT) from public servers to adjust time"
	ECODE=1
fi

rm -f -- "$F"
exit $ECODE