背景

机器每次机启后时间就会出现异常,因为机器无法访问外网,只能访问局域网的ntp服务,所以需要保证局域网内部有ntp服务,如何安装ntp服务,参考Ubuntu20.04 Ntp服务安装及验证。

网络时间协议Network Time Protocol(NTP) 是一种确保时钟保持准确的方法。如果可以访问互联网,只需安装ntp的客户端软件到互联网上的公共ntp服务器自动修正时间即可

一、系统时间和硬件时间

Linux在默认情况下,系统时间和硬件时间并不会自动同步。而是以异步的方式运行,互不干扰。其中硬件时间的运行,是靠Bios电池来维持,而系统时间,是用CPU 时钟来维持的。

在系统开机的时候,会自动从Bios中取得硬件时间,设置为系统时间。

1.1 date命令

用来查看和设置系统时间

date   #查看系统当前时间
sudo date -s "2023-03-18 11:16:10"  #修改系统时间为 "xxxx-xx-xx xx:xx:xx"
===============================================================================
nvidia@nvidia-desktop:~$ date
Вт мар 18 11:16:27 +08 2023
nvidia@nvidia-desktop:~$
nvidia@nvidia-desktop:~$
nvidia@nvidia-desktop:~$ sudo date -s "2023-03-18 11:16:10"
[sudo] password for nvidia:
Вт мар 18 11:16:10 +08 2023
nvidia@nvidia-desktop:~$

硬件时间的设置,可以用hwclock

1.2 hwclock 命令

查看当前硬件时间

注意:hwclock 所有命令需要使用root 权限

nvidia@nvidia-desktop:~$ hwclock
hwclock: Cannot access the Hardware Clock via any known method.
hwclock: Use the --debug option to see the details of our search for an access method.
nvidia@nvidia-desktop:~$
nvidia@nvidia-desktop:~$
nvidia@nvidia-desktop:~$ sudo hwclock
2023-03-21 11:18:49.607690+0800
nvidia@nvidia-desktop:~$

将系统时间同步到硬件时间

hwclock -w

将硬件时间同步到系统时间

hwclock -s

二、不同机器间时间同步

为了避免主机时间因为长期运作下所导致的时间偏差,进行时间同步(synchronize)的工作是非常必要的。Linux系统下,一般使用ntp服务器来同步不同机器的时间。一台机器,可以同时是ntp服务器和ntp客户机。

2.1 ntpdate命令实现

ntpdate 安装:

yum install ntpdate -y   # Centos系统
======================================
sudo apt install ntpdate  # Ubuntu系统

时间同步

sudo ntpdate -u cn.pool.ntp.org
18 Mar 18:25:22 ntpdate[18673]: adjust time server 84.16.73.33 offset 0.015941 sec

使用ntpdate 只是强制将系统时间设置为ntp服务器时间,如果cpu tick有问题,时间还是会不准。所以,一般配合cron命令,来进行定期同步设置。比如,在crontab中添加:

sudo crontab -e0 12 * * * * /usr/sbin/ntpdate 192.168.10.110

上述命令的意思是:每天的12点整,从192.168.10.110 ntp服务器同步一次时间(前提是 192.168.10.110有ntp服务)。

2.2 Ntp客户端代码实现

本质上还是创建socket连接去获取ntp服务的时间与本地时间比较,不一致修改本机时间即可。

NtpClient.h

//
// Created by lwang on 2023-03-18.
//
#ifndef NTP_CLIENT_H
#define NTP_CLIENT_H#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <iostream>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <endian.h>
#include <map>
#include <string>
#include <mutex>using namespace std;#define NTP_LI          0
#define NTP_VERSION_NUM 3#define NTP_MODE_CLIENT 3
#define NTP_MODE_SERVER 4#define NTP_STRATUM 0
#define NTP_POLL    4
#define NTP_PRECISION -6#define NTP_MIN_LEN   48#define NTP_SERVER_PORT 123
#define NTP_SERVER_ADDR "119.28.183.184"#define TIMEOUT 2#define BUFSIZE 1500#define JAN_1970 0x83aa7e80#define NTP_CONV_FRAC32(x) (uint64_t)((x) * ((uint64_t)1 << 32))
#define NTP_REVE_FRAC32(x) ((double)((double)(x) / ((uint64_t)1 << 32)))#define NTP_CONV_FRAC16(x) (uint32_t)((x) * ((uint32_t)1 << 16))
#define NTP_REVE_FRAC16(x) ((double)((double)(x) / ((uint32_t)1 << 16)))#define USEC2FRAC(x) ((uint32_t)NTP_CONV_FRAC32((x) / 1000000.0))
#define FRAC2USEC(x) ((uint32_t)NTP_REVE_FRAC32((x)*1000000.0))#define NTP_LFIXED2DOUBLE(x) ((double)(ntohl(((struct l_fixedpt *)(x))->intpart) - JAN_1970 + FRAC2USEC(ntohl(((struct l_fixedpt *)(x))->fracpart)) / 1000000.0))struct s_fixedpt
{uint16_t intpart;uint16_t fracpart;
};struct l_fixedpt
{uint32_t intpart;uint32_t fracpart;
};struct ntphdr
{#if __BYTE_ORDER == __BID_ENDIANunsigned int ntp_li : 2;unsigned int ntp_vn : 3;unsigned int ntp_mode : 3;
#endif
#if __BYTE_ORDER == __LITTLE_ENDIANunsigned int ntp_mode : 3;unsigned int ntp_vn : 3;unsigned int ntp_li : 2;
#endifuint8_t ntp_stratum;uint8_t ntp_poll;int8_t ntp_precision;struct s_fixedpt ntp_rtdelay;struct s_fixedpt ntp_rtdispersion;uint32_t ntp_refid;struct l_fixedpt ntp_refts;struct l_fixedpt ntp_orits;struct l_fixedpt ntp_recvts;struct l_fixedpt ntp_transts;
};class NtpClient {public:NtpClient();virtual ~NtpClient();void        GetNtpTime(std::string &ntpTime);in_addr_t   HostTransfer(const char *host);int         PaddingNtpPackage(void *buf, size_t *size);double      GetOffset(const struct ntphdr *ntp, const struct timeval *recvtv);
private:int m_sockfd;};#endif /* NTP_CLIENT_H */

NtpClient.cpp

//
// Created by lwang on 2023-03-18.
//#include "NtpClient.h"NtpClient::NtpClient() { }
NtpClient::~NtpClient() {}in_addr_t NtpClient::HostTransfer(const char *host)
{in_addr_t saddr;struct hostent *hostent;if ((saddr = inet_addr(host)) == INADDR_NONE){if ((hostent = gethostbyname(host)) == NULL){return INADDR_NONE;}memmove(&saddr, hostent->h_addr, hostent->h_length);}return saddr;
}int NtpClient::PaddingNtpPackage(void *buf, size_t *size) // 构建并发送NTP请求报文
{if (!size)return -1;struct ntphdr *ntp;struct timeval tv;memset(buf, 0, BUFSIZE);ntp = (struct ntphdr *)buf;ntp->ntp_li = NTP_LI;ntp->ntp_vn = NTP_VERSION_NUM;ntp->ntp_mode = NTP_MODE_CLIENT;ntp->ntp_stratum = NTP_STRATUM;ntp->ntp_poll = NTP_POLL;ntp->ntp_precision = NTP_PRECISION;gettimeofday(&tv, NULL); // 把目前的时间用tv 结构体返回ntp->ntp_transts.intpart = htonl(tv.tv_sec + JAN_1970);ntp->ntp_transts.fracpart = htonl(USEC2FRAC(tv.tv_usec));*size = NTP_MIN_LEN;return 0;
}double NtpClient::GetOffset(const struct ntphdr *ntp, const struct timeval *recvtv) // 偏移量
{double t1, t2, t3, t4;t1 = NTP_LFIXED2DOUBLE(&ntp->ntp_orits);t2 = NTP_LFIXED2DOUBLE(&ntp->ntp_recvts);t3 = NTP_LFIXED2DOUBLE(&ntp->ntp_transts);t4 = recvtv->tv_sec + recvtv->tv_usec / 1000000.0;return ((t2 - t1) + (t3 - t4)) / 2;
}void NtpClient::GetNtpTime(std::string &ntpTime)
{char buffer[64] = {0};char cmd[128] = {0};tm *local;char buf[BUFSIZE];size_t nbytes;int maxfd1;struct sockaddr_in servaddr;fd_set readfds;struct timeval timeout, recvtv, tv;double offset;servaddr.sin_family = AF_INET;servaddr.sin_port = htons(NTP_SERVER_PORT);servaddr.sin_addr.s_addr = HostTransfer(NTP_SERVER_ADDR);if ((m_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror("socket error");return ;}if (connect(m_sockfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr)) != 0){perror("connect error");return ;}nbytes = BUFSIZE;if (PaddingNtpPackage(buf, &nbytes) != 0){fprintf(stderr, "construct ntp request error \n");exit(-1);}send(m_sockfd, buf, nbytes, 0);FD_ZERO(&readfds);FD_SET(m_sockfd, &readfds);maxfd1 = m_sockfd + 1;timeout.tv_sec = TIMEOUT;timeout.tv_usec = 0;if (select(maxfd1, &readfds, NULL, NULL, &timeout) > 0){if (FD_ISSET(m_sockfd, &readfds)){if ((nbytes = recv(m_sockfd, buf, BUFSIZE, 0)) < 0){perror("recv error");exit(-1);}// 计算C/S时间偏移量gettimeofday(&recvtv, NULL);offset = GetOffset((struct ntphdr *)buf, &recvtv);gettimeofday(&tv, NULL);tv.tv_sec += (int)offset;tv.tv_usec += offset - (int)offset;local = localtime((time_t *)&tv.tv_sec);strftime(buffer, 64, "%Y-%m-%d %H:%M:%S", local);ntpTime = std::string(buffer);}}return ;
}

main.cpp

#include "NtpClient.h"int main()
{std::string ntpTime = "";char curBuf[64] = {0};struct timeval cur;tm *local;NtpClient client;client.GetNtpTime(ntpTime);cout << "ntpTime: " << ntpTime << endl;gettimeofday(&cur, NULL);local = localtime((time_t *)&cur.tv_sec);strftime(curBuf, 64, "%Y-%m-%d %H:%M:%S", local);std::string curTime = std::string(curBuf);cout << "curTime: " << curTime << endl;if (curTime != ntpTime){cout << "start time calibrate!"  << endl;std::string cmd = "sudo date -s \"" + ntpTime +  "\"";system(cmd.c_str());cout << "cmd: " << cmd << endl;}else{cout << "time seem"  << endl;}return 0;
}

推荐一个零声学院免费教程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:

Linux时间校准(ntpdate及NTP客户端代码校准示例)相关推荐

  1. windows2012同步linux时间,Windows server2012时间同步NTP配置

    遇到经常服务器时间无法同步,可以自己建立一台时间同步服务器,NTP配置如下: 一.服务端配置 (Ntp服务器,客户端将根据这台服务器的时间进行同步) 1.微软键+R键,进入"运行" ...

  2. 【DIY】入门必看:arduino入门实用教程,esp8266获取互联网时间,nodemcu制作NTP客户端获取显示互联网时间...

    今天使用ESP8266(nodemcu)做一个互联网时间显示器,没错从互联网获取时间,精准高效,简单粗暴,不用对时.入门级详细教程哦! 按照国际惯例先展示成品:                     ...

  3. windows ntp客户端配置,连接linux npt服务。

    服务器操作系统使用的centos系统.服务器之间通过NTP服务进行时间同步,客户端使用的window,需要同步服务端的时间. 配置windows ntp客户端步骤如下: 运行gpedit.msc 点击 ...

  4. Linux 小知识翻译 - 「NTP」

    这周聊聊「NTP」. 上次,聊了「时区」,也就是时间相关的话题. NTP是「Network Time Protocol」的简称,是为了将网络中计算机的时钟同步到正确时间的协议. PC内部的时钟是相当不 ...

  5. Linux时间 时区 同步

    Linux时间 时区 同步卸载ntp服务 pi@raspberrypi:~ $ sudo apt-get remove ntp安装ntpdate客户端 pi@raspberrypi:~ $ sudo ...

  6. linux锁定系统时间设置,Linux时间设置系统时间、硬件时间和时间服务

    Linux有两个时间,一个是系统时间,一个是RTC时间(也叫硬件时间). Linux系统启动时,会自动获取硬件时间,设置为系统时间. 一.查询系统时间: 查询系统时间:date 查询/设置硬件时间: ...

  7. Linux:命令date、ntp查看和修改(校准)时间和地区。

    Linux:命令date.ntp查看和修改(校准)时间和地区. date -d 不仅可以+1还可以加其他数字,+表达后多久,-表达前多久: 备注:中国所在的时区是东八区 单独使用date时,会出现一串 ...

  8. linux服务器ntp客户端配置【转】

    转自:https://www.cnblogs.com/kerrycode/archive/2015/08/20/4744804.html 在Linux系统中,为了避免主机时间因为在长时间运行下所导致的 ...

  9. Linux 时间一致性环境NTP/Chrony服务器部署配置

    一.背景 生产环境中,一个业务系统往往涉及几十台甚至上百台主机或云主机构成,有些管理系统对整个环境时间一致性由强要求,即使没有,保证环境中时间的一致性,有利于业务交互时时间匹配,保证事务的一致性,甚至 ...

最新文章

  1. 美国两政府网站被挂马 以性丑闻女星为诱饵
  2. 80%的企业社会化商务应用可能无法取得预期效果
  3. BSPreloadTableVew带有预加载功能的tableView
  4. ES6 使用数据类型Set求交集、并集、差集
  5. PAT刷题 (Java语言)
  6. ZOJ - 2972 Hurdles of 110m(记忆化搜索/动态规划)
  7. 【题解】 P2151 [SDOI2009]HH去散步
  8. 从客户端登陆服务器的配置文件,BLE模式和配置文件
  9. UI控件之UISlider
  10. Ranking the Cows(POJ-3275 )
  11. 收获,不止SQL优化——抓住SQL的本质--第十一章
  12. click事件在什么时候出发_什么是移动端?
  13. Unreal Engine 4 —— 使用反汇编来确定该进行优化的地方
  14. 20145236 《Java程序设计》 第6周学习总结
  15. android9 前台服务通知_Android通知概览
  16. 匿名管道(4种情况 )
  17. Word公式自动编号
  18. 关于金蝶K3系统(工业)供应链部分,使用前需要基本了解的一些信息
  19. C语言实现之数字中的最大数字组合
  20. 2014-07-08 hibernate tenancy

热门文章

  1. windows采集扬声器声音
  2. js replace方法解决全部替换的问题(替换目标字符串 可以多个)
  3. 怀念在青岛的那段日子
  4. animegan2-pytorch 实现相机照片 转化为动漫滤镜效果图片
  5. 云服务器部署和安装开源笔记leanote完整教程
  6. 交换机性能指标:背板带宽、交换容量、包转发率
  7. LevOJ P1135NBA总冠军
  8. 常见的Python编程工作岗位有哪些?
  9. python复制指定文件到指定文件夹
  10. 低价格横梁式货架给物流仓库仓储管理带来了哪些用途?