Merge remote-tracking branch 'adsb/fordsa'
[mirror/dsa-nagios.git] / dsa-nagios-checks / checks / dsa-check-timedatectl
1 #!/bin/bash
2
3 # Copyright 2016 Peter Palfrader
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be
14 # included in all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24
25 set -e
26 set -u
27
28 MAX=2
29 SYNSTATUSONLY="0"
30
31 usage(){
32         ret=$1
33
34         cat <<EOF
35 $0: usage:
36         $0 <options>
37
38         Check NTP sync status (per timedatectl's output) and offset to RTC clock.
39         The latter is particularly interesting for VMs.
40
41         -o <secs>   Maximum offset to tolerate (Default: $MAX)
42         -s          Check sync status only, do not diff against RTC.
43 EOF
44
45         exit $ret
46 }
47
48 while getopts o:sh opt ; do
49         case "$opt" in
50                 o) MAX="$OPTARG" ;;
51                 s) SYNSTATUSONLY="1";;
52                 h) usage 0
53         esac
54 done
55 shift $(($OPTIND - 1))
56 if [ "$#" -gt 0 ]; then
57         usage 1 >&2
58 fi
59
60
61 temp="$(mktemp)"
62 trap "rm -f '$temp'" EXIT
63
64 systemdversion="$(timedatectl --version | head -n1 | awk '{print $2}')"
65 if [ -z "$systemdversion" ]; then
66         echo "Unknown: Cannot get systemd version"
67         exit 3
68 fi
69 if [ "$systemdversion" -lt 241 ] ; then # before buster (Debian 10)
70         LC_ALL=C timedatectl > "$temp"
71         ut=$(sed '/Universal time:/ { s/^[^:]*: *//; p}; d' "$temp")
72         rtc=$(sed '/RTC time:/ { s/^[^:]*: *//; p}; d' "$temp")
73         ntpenabled=$(sed '/\(NTP enabled\|Network time on\|NTP service\):/ { s/^[^:]*: *//; p}; d' "$temp")
74         ntpsynced=$(sed '/\(NTP synchronized\|System clock synchronized\):/ { s/^[^:]*: *//; p}; d' "$temp")
75 else
76         LC_ALL=C timedatectl show > "$temp"
77         ut=$(sed '/^TimeUSec=/ { s/^[^=]*=//; p}; d' "$temp")
78         rtc=$(sed '/^RTCTimeUSec=/ { s/^[^=]*=//; p}; d' "$temp")
79         ntpenabled=$(sed '/^NTP=/ { s/^[^=]*=//; p}; d' "$temp")
80         ntpsynced=$(sed '/^NTPSynchronized=/ { s/^[^=]*=//; p}; d' "$temp")
81         if [ "$ntpenabled" = "no" ]; then # in buster (Debian 10) ntpenabled no longer also considers the ntp service
82                 ntp_status=$(systemctl is-enabled 'ntp.service' 2>/dev/null) && rc=$? || rc=$?
83                 if [ "$rc" = 0 ] && [ "$ntp_status" = "enabled" ] ; then
84                         if systemctl --quiet is-active ntp.service; then
85                                 ntpenabled=yes
86                         fi
87                 fi
88         fi
89 fi
90
91 uts=$(TZ=UTC date -d "$ut" +%s)
92 rtcs=$(TZ=UTC date -d "$rtc" +%s 2>/dev/null || echo "N/A")
93 if [ "$rtcs" != "N/A" ]; then
94         delta=$((uts - rtcs))
95 fi
96
97 if [ "$SYNSTATUSONLY" -ge 1 ]; then
98         if [ "$ntpsynced" != "yes" ]; then
99                 echo "Warning: not synced with NTP."
100                 exit 1
101         fi
102 else
103         if [ "$rtcs" = "N/A" ]; then
104                 echo "Warning: Cannot parse RTC $rtc."
105                 exit 1
106         fi
107
108         if [ "$delta" -lt "-$MAX" ] ||
109            [ "$delta" -gt "$MAX" ]; then
110                 echo "Warning: time desync $delta: RTC vs. system time: $rtc vs. $ut"
111                 exit 1
112         fi
113
114         if [ "$ntpenabled" != "yes" -a "$ntpenabled" != "active"  ]; then
115                 echo "Warning: NTP not enabled!"
116                 exit 1
117         fi
118
119         if [ "$ntpsynced" != "yes" ]; then
120                 echo "Warning: not synced with NTP (but clock is OK for now)."
121                 exit 1
122         fi
123 fi
124
125 echo "OK: synced at $ut."