2 # -*- coding: utf-8 -*-
4 ntpwait - Wait for ntpd to stabilize the system clock.
5 USAGE: ntpwait [-n tries] [-s sleeptime] [-v] [-h]
7 -n, --tries=num Number of times to check ntpd
8 -s, --sleep=num How long to sleep between tries
9 -v, --verbose Be verbose
11 -V, --version Output version information and exit
13 Options are specified by doubled hyphens and their name or by a single
14 hyphen and the flag character.
16 A spurious 'not running' message can result from queries being disabled.
19 # Copyright the NTPsec project contributors
21 # SPDX-License-Identifier: BSD-2-Clause
23 # Because we've actually seen this fail on a ^C during import of ntp.packet.
26 signal
.signal(signal
.SIGINT
, lambda signal
, frame
: sys
.exit(2))
37 except ImportError as e
:
39 "ntpwait: can't find Python NTP library.\n")
40 sys
.stderr
.write("%s\n" % e
)
44 class Unbuffered(object):
45 def __init__(self
, stream
):
48 def write(self
, data
):
49 self
.stream
.write(data
)
52 def __getattr__(self
, attr
):
53 return getattr(self
.stream
, attr
)
56 if __name__
== "__main__":
57 bin_ver
= "ntpsec-@NTPSEC_VERSION_EXTENDED@"
58 ntp
.util
.stdversioncheck(bin_ver
)
60 (options
, arguments
) = getopt
.getopt(sys
.argv
[1:], "hn:s:vV", [
61 "tries=", "sleep=", "verbose", "help", "version"
63 except getopt
.GetoptError
as err
:
64 sys
.stderr
.write(str(err
) + "\n")
69 for (switch
, val
) in options
:
70 if switch
in ("-n", "--tries"):
71 errmsg
= "Error: -n parameter '%s' not a number\n"
72 tries
= ntp
.util
.safeargcast(val
, int, errmsg
, __doc__
)
73 elif switch
in ("-s", "--sleep"):
74 errmsg
= "Error: -s parameter '%s' not a number\n"
75 sleep
= ntp
.util
.safeargcast(val
, int, errmsg
, __doc__
)
76 elif switch
in ("-v", "--verbose"):
78 elif switch
in ("-h", "--help"):
79 sys
.stdout
.write(__doc__
)
81 elif switch
in ("-V", "--version"):
82 print("ntpwait %s" % ntp
.util
.stdversion())
86 sys
.stdout
= Unbuffered(sys
.stdout
)
88 basetime
= ntp
.util
.monoclock()
90 sys
.stdout
.write("Waiting for ntpd to synchronize... ")
92 for i
in range(1, tries
):
93 session
= ntp
.packet
.ControlSession()
95 if not session
.openhost("localhost"):
97 sys
.stdout
.write("\bntpd is not running!\n")
102 msg
= session
.doquery(2) # Request system variables
103 except ntp
.packet
.ControlException
as e
:
104 sys
.stderr
.write("localhost: timed out, nothing received\n")
105 sys
.stderr
.write(e
.message
)
108 sys
.stdout
.write("\b" + "*+:."[i
% 4])
113 sys
.stderr
.write(repr(session
.response
) + "\n")
115 if msg
and msg
.startswith("***"):
117 sys
.stdout
.write("\b" + msg
+ "\n")
120 m
= re
.search(r
"leap=([^,]*),", repr(session
.response
))
122 leap
= int(m
.group(1))
124 sys
.stdout
.write("\bLeap status not available\n")
127 if leap
== ntp
.magic
.LEAP_NOTINSYNC
:
129 sys
.stdout
.write("\b" + "*+:."[i
% 4])
134 if leap
in (ntp
.magic
.LEAP_NOWARNING
, ntp
.magic
.LEAP_ADDSECOND
,
135 ntp
.magic
.LEAP_DELSECOND
):
136 # We could check "sync" here to make sure we like the source...
138 sys
.stdout
.write("\bOK! (%.1f seconds)\n" %
139 (ntp
.util
.monoclock() - basetime
))
142 sys
.stdout
.write("\bUnexpected 'leap' status <%s>\n" % leap
)
146 sys
.stdout
.write("\bNo!\nntpd did not synchronize.\n")