NTP时间同步问题
最近发现有个服务器时间差了几秒钟,查看ntpd服务是开启的,只不过同步都没有成功。重启,重新配置时钟源,等等一通折腾,还是没有连接上。
使用ntpq -p 命令查看状态是这样的:
每一列的含义如下所示:
remote:远程NTP服务器的IP地址或域名,带 “*” 的表示本地NTP服务器与该服务器同步。
refid: 远程NTP服务器的上层服务器的IP地址或域名。
st: 远程NTP服务器所在的层数。
t: 本地NTP服务器与远程NTP服务器的通信方式,u: 单播; b: 广播; l: 本地。
when: 上一次校正时间与现在时间的差值。
poll: 本地NTP服务器查询远程NTP服务器的时间间隔。
reach: 是一种衡量前8次查询是否成功的位掩码值,377表示都成功,0表示不成功。
delay: 网络延时,单位是10的-6次方秒。
offset: 本地NTP服务器与远程NTP服务器的时间偏移。
jitter: 查询偏差的分布值,用于表示远程NTP服务器的网络延时是否稳定,单位为10的-6次方秒
而正常的ntpq -p 命令查看状态可能如下:
使用 ntpdate -d 114.118.7.161 指定同步, 连接不上,并报no server suitable for synchronization found,如下图:
并同时使用tcpdump -i ens11f1 host 114.118.7.161 抓包,发现只有往外发的包,没有回的包,如下:
这台服务器部署在一个现场,没有有线网络,是通过4G路由器插卡上网的,登录到路由器上再抓包:可以看到能ping通,有ICMP的发包和收包,但是ntp只有发包,没有收到ntp的回包。
难道是服务器端有问题吗,再验证下。
换一台本地服务器,执行ntpdate -d 114.118.7.161并同时抓包:
下图为ntpdate执行情况:可以同步。
下图为tcpdump -i ens11f0 host 114.118.7.161 执行情况:可以看到有ntp发包也有ntp收包,证明服务器也是可用的。
问题很明显了,应该是出在现场服务器连接的4G路由器上,不知道路由器是怎么处理这个ntp包的。现场设备没办法换,只能用以前写的shell脚本来同步,只能是秒级的同步了。如下:
#!/bin/bash
source /etc/profile
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin:
source ~/.bash_profile
remoteuser="timing"
remoteip="192.168.1.11"
# 工作文件夹
basicdir="/home/timing/settiming/"
if [ ! -d ${basicdir} ];then
mkdir -p ${basicdir}
fi
# 日志路径
logdir=${basicdir}"log/"
if [ ! -d ${logdir} ];then
mkdir -p ${logdir}
fi
function writelog () #写日志
{
CUR_DATE="`date +%Y%m%d`" #当前日期
CUR_HOUR="`date +"%H"`" #当前小时
CUR_TIME="`date +%Y-%m-%d_%H:%M:%S`" #当前时间
echo ${CUR_TIME}":"${1}
echo ${CUR_TIME}":"${1} >> ${logdir}"/"${CUR_DATE}".log"
}
cd ${basicdir}
writelog "-------------------------------------------------"
localtime="`date +'%Y-%m-%d %H:%M:%S'`"
writelog "本地时间为:${localtime}"
# 获取远方机器时间
remotetime=`sshpass -p'123456' ssh ${remoteuser}@${remoteip} "date +'%Y-%m-%d %H:%M:%S'"`
writelog "获取远方机器时间为:${remotetime}"
# 获取远方机器时间
lenret=`expr length "${remotetime}"`
writelog "获取远方机器时间字符串长度为:${lenret}"
# 判断远方机器时间获取成功还是失败
if [ ${lenret} -eq 19 ];then
writelog "判断获取远方机器时间成功!"
remotesec=`date -d "${remotetime}" +%s`
writelog "远方机器时间戳为:${remotesec}"
localtime="`date +'%Y-%m-%d %H:%M:%S'`"
writelog "本地时间为:${localtime}"
localsec=`date -d "${localtime}" +%s`
writelog "本地时间戳为:${localsec}"
dif=`expr ${remotesec} - ${localsec}`
writelog "远方-本地 时间相差[${dif}]秒"
if [[ ${dif} -gt 5 ]];then
writelog "时间相差大于5秒"
usedif=5
elif [[ ${dif} -lt -5 ]];then
writelog "时间相差小于-5秒"
usedif=-5
else
writelog "时间相差在-5~5秒之间,不进行时间调整!即将退出"
exit 0
fi
writelog "对时调整时间[${usedif}]秒"
modifysec=`expr ${localsec} + ${usedif}`
writelog "对时调整时间戳为:${modifysec}"
modifytime=`date -d @${modifysec} +'%Y-%m-%d %H:%M:%S'`
writelog "对时调整时间字符串为:${modifytime}"
writelog "执行时间调整命令 date -s "
sudo date -s "${modifytime}"
sudo hwclock -w
localtime="`date +'%Y-%m-%d %H:%M:%S'`"
writelog "本地时间为:${localtime}"
else
writelog "判断获取远方机器时间失败!"
fi
脚本执行需要安装sshpass,和在服务器增加用户的sodu执行权限。
执行visudo,增加两行,settime为本机执行同步脚本的用户。
用系统守护crontab启动该脚本,大概一个小时执行一次就差不多了。
效果大概如下: