While ntp may be a great protocol, I find it quite bloated and slow for the simple purpose of just setting a local date and time to a reference clock. I do not need 20ms accuracy on a notebook's clock
.
Thus I use(d) rdate for a decade now but the public rdate servers are slowly dying out. So I'm replacing it more and more with htpdate which works quite nicely. It's written in C and a perl alternative is available on the author's site. There is also a forked windows version of it available.
Developing a bit larger bash script (which syncs a few servers), I wondered whether I could realize the time sync part in bash as well.
It's quite possible:
# open a tcp connection to www.google.com
exec 3<>/dev/tcp/www.google.com/80
# say hello HTTP-style
echo -e "GET / HTTP/1.0\n\n">&3
# parse for a Date: line and with a bit of magic throw the date-string at the date command
LC_ALL=C LANG=en date --rfc-2822 --utc -s "$(head <&3 | grep -i "Date: " | sed -e s/Date\:\ //I)"
# close the tcp connection
exec 3<&-
Simple, eh?
A stand-alone version is available as httpdate and looks like this in v0.1:
#!/bin/bash
#
# Purpose: display or set date from a host via http
#
# Requires: bash, ping, head, date, grep & sed
# Autor: Daniel Lange, http://daniel-lange.com/software/
# License: GPL v3 or later, http://www.gnu.org/licenses/
#
# Version: v0.1, 08-10-22, initial release
#
if [ "$1" = "-h" -o "$1" = "--help" ] ; then
echo "$0 v0.1 (c) Daniel Lange, 2008. Released under the GNU GPL v3 or later."
echo "Usage: $0 <-d|-s> <HOST>"
echo " -d = display date (default)"
echo " -s = set date (may require root privileges)"
echo " HOST = FQDN of the server to retrieve the Date: header from"
echo " (default: www.google.com)"
exit 0
fi
if [ "$1" != "-d" -a "$1" != "-s" ] ; then
echo "Error: either -d or -s expected as first argument".
exit 1
fi
if [ "$#" -gt 2 ] ; then
echo "Error: too many arguments, use -h for help"
exit 2
fi
DATE_OPTION="$1"
DATE_HOST="${2:-www.google.de}"
ping -q -c 1 -w 10 -W 10 $DATE_HOST > /dev/null 2>&1
if [ $? -ne 0 ] ; then
echo "Error: Host $DATE_HOST not found (or ping missing)."
exit 3
fi
exec 3<>/dev/tcp/$DATE_HOST/80
echo -e "GET / HTTP/1.0\n\n">&3
LC_ALL=C LANG=en_EN date --rfc-2822 --utc $DATE_OPTION "$(head <&3 | grep -i "Date: " | sed -e s/Date\:\ //I)"
exec 3<&-
Update:
27.09.09: Just FYI: The Debian/Ubuntu (before 09.10,
launchpad bug entry) bash does not have the capability to use
/dev/tcp. It's been compiled with
–disable-net-redirections.