Linux强制与NTP服务器同步时间

Redhat 7:

先停止ntp服务,然后强制与NTP服务器的时间同步,完成后再启动ntp服务。
# systemctl stop ntpd
# ntpdate ntp-server-ip
(如果想不停止ntp服务来执行ntpdate,那么可以加上-u选项。)
# systemctl start ntpd


SUSE:
# /etc/init.d/ntp ntptimeset


来源:How to forcefully sync date and time using the NTP server in Linux


ntpq -p命令输出说明
在这里插入图片描述

位置标志含义
remote最前面*响应的NTP服务器和最精确的服务器
remote最前面+响应这个查询请求的NTP服务器
remote最前面blank(空格)没有响应的NTP服务器
第1列remote响应这个请求的NTP服务器的名称
第2列refidNTP服务器使用的更高一级服务器的名称
第3列st正在响应请求的NTP服务器的级别
第4列when上一次成功请求之后到现在的秒数
第5列poll本地和远程服务器多少时间进行一次同步,单位秒,在一开始运行NTP的时候这个poll值会比较小,服务器同步的频率大,可以尽快调整到正确的时间范围,之后poll值会逐渐增大,同步的频率也就会相应减小
第6列reach用来测试能否和服务器连接,是一种衡量前8次查询是否成功的位掩码值,每成功连接一次它的值就会增加,377表示都成功,0表示不成功。它是八进制数,正常情况下值为[0, 1, 3, 7, 17, 37, 77, 177, 377],对应的二进制为[0, 1, 11, 111, 1111, 11111, 111111, 1111111, 11111111],ntp服务启动后,reach就以poll值为周期与ntp server通信,为了方便理解,我们可以简单的认为每次ping一下上层ntp server,如果成功,那reach就向左移一位,右边补1,如果失败,则右边补0,所以如果reach不是上面给出的枚举值,那就是在通信过程中出错了。当reach 达到17时(对应1111,即最近的4次通信都成功了),那才开始同步时间,这时,remote项对应的域名或IP列表有,其中一个前面会有号,表示该IP就是NTP server。而在开始同步时间之前,当客户端访问NTP server时,都会出现stratum 16,no server suitable for synchronization found这样的错误。也就是说如果你在NTP server主机上重启了ntp服务,那要等4poll秒(在前4次通信都是成功的前提下),该NTP server才与上层NTP server开始同步时间,而且只有当开始同步时,该NTP server才能为其它客户端提供NTP服务。因此,你在/etc/ntp.conf中设置的同步周期minpoll maxpoll不能太大,因为每次ntp服务重启后,要等4倍长的时间才能开始同步。
第7列delay从本地机发送同步要求到ntp服务器的往返时间
第8列offset主机通过NTP时钟同步与所同步时间源的时间偏移量,单位为毫秒,offset越接近于0,主机和ntp服务器的时间越接近
第9列jitter统计了在特定个连续的连接数里offset的分布情况。简单地说这个数值的绝对值越小,主机的时间就越精确

附:
简单配置ntp服务器步骤:
1)编辑/etc/ntp.conf文件,加入以下两行:
server 127.127.1.0
fudge 127.127.1.0 stratum 6

2)启动ntpd服务
# systemctl start ntpd
# systemctl status ntpd
# systemctl enable ntpd
# ntpq -p



ntp异常问题:

如果与ntp时钟源的时间相差太大(大于1000秒),ntp服务可能会退出,请参考以下链接:
在这里插入图片描述
参考:
How far off is “too far off” for ntpd?
Miscellaneous Options

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现一个完整的NTP服务器需要考虑很多因素,包括网络通信、精确的时间同步、安全性等等。以下是一个使用C语言实现的简单NTP服务器的示例,包括了基本的时间同步和网络通信功能。 1. 创建TCP服务器 首先,我们需要创建一个TCP服务器来接收客户端的连接请求。在C语言中,可以使用socket库来实现网络通信功能。以下是一个简单的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 123 // NTP端口号 int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; char* message = "Hello from server"; // 创建服务器端socket if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置socket选项 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } // 设置服务器地址和端口号 address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // 绑定socket到服务器地址和端口号 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连接请求 if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } printf("NTP server is running on port %d\n", PORT); // 接收客户端连接请求并发送响应 while (1) { if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("accept"); exit(EXIT_FAILURE); } // 发送欢迎消息给客户端 send(new_socket, message, strlen(message), 0); printf("Hello message sent\n"); // 关闭连接 close(new_socket); } return 0; } ``` 2. 实现NTP协议 接下来,我们需要实现NTP协议来同步时间NTP协议包括客户端和服务器端两部分,客户端向服务器发送时间请求,服务器返回准确的时间。以下是一个简单的NTP服务器实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <time.h> #define PORT 123 // NTP端口号 #define NTP_EPOCH_OFFSET 2208988800UL // NTP时间戳与UNIX时间戳的偏移值 // NTP协议头部 typedef struct { uint8_t leap_ver_mode; // 协议版本和模式 uint8_t stratum; // 时间源层级 uint8_t poll; // 客户端请求间隔 uint8_t precision; // 时间精度 uint32_t root_delay; // 本地时钟与上层时钟的延迟 uint32_t root_dispersion; // 本地时钟与上层时钟的偏移 uint32_t reference_id; // 参考时钟源ID uint64_t reference_timestamp; // 参考时刻 uint64_t origin_timestamp; // 客户端发起请求的时刻 uint64_t receive_timestamp; // 服务器接收到请求的时刻 uint64_t transmit_timestamp; // 服务器发送响应的时刻 } ntp_packet; // 获取当前时间NTP时间戳 uint64_t get_ntp_timestamp() { struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); uint64_t ntp_timestamp = ((uint64_t)ts.tv_sec + NTP_EPOCH_OFFSET) << 32; ntp_timestamp |= ((uint64_t)ts.tv_nsec * (1LL << 32)) / 1000000000LL; return ntp_timestamp; } int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = {0}; char* message = "Hello from server"; // 创建服务器端socket if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置socket选项 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } // 设置服务器地址和端口号 address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // 绑定socket到服务器地址和端口号 if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连接请求 if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } printf("NTP server is running on port %d\n", PORT); // 接收客户端连接请求并发送响应 while (1) { if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("accept"); exit(EXIT_FAILURE); } // 构造NTP响应包 ntp_packet response; memset(&response, 0, sizeof(response)); response.leap_ver_mode = 0x1b; // 协议版本为3,模式为服务器 response.stratum = 0; // 时间源层级为0,表示本地时钟 response.reference_id = htonl(0x7f000001); // 参考时钟源ID为127.0.0.1 response.reference_timestamp = get_ntp_timestamp(); // 参考时刻为当前时间 response.origin_timestamp = 0; // 客户端发起请求的时刻为0 response.receive_timestamp = 0; // 服务器接收到请求的时刻为0 response.transmit_timestamp = get_ntp_timestamp(); // 服务器发送响应的时刻为当前时间 // 发送NTP响应包给客户端 send(new_socket, &response, sizeof(response), 0); printf("NTP response sent\n"); // 关闭连接 close(new_socket); } return 0; } ``` 3. 安全性考虑 NTP协议在传输过程中可能会遭受到攻击,如伪造请求、篡改响应等。为了提高安全性,可以使用加密和身份验证机制来保护NTP协议的传输安全。例如,使用TLS协议加密NTP请求和响应,使用数字证书验证服务器的身份,防止中间人攻击等。 以上是一个简单的使用C语言实现的NTP服务器的示例,其中包括了基本的时间同步和网络通信功能。实际上,NTP协议的实现非常复杂,需要考虑很多因素,如时钟精度、时钟同步算法、时钟漂移等,需要仔细研究和实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值