我的 Linux 机器上的时间不会停滞不前。我需要测试我们的服务器仅在周六发生的问题。
- CentOS 6.5 64位
- 我已经关闭了 NTPD。 (
service ntpd stop
和chkconfig ntpd off
) - 我将虚拟 BIOS/硬件时钟设置为 2015 年 5 月 2 日
- 将时间更改为未来或过去具有相同的效果。
- 我在命令行上设置日期
date --set "02 May 2015 11:00:00"
date
正确回复并显示日期为 2015 年 5 月 2 日cron.d
、cron.daily
、cron.hourly
等中与时间/ntp 无关。
几分钟后,时间将自动回到正确的日期。
还有什么可以不断地改变时间呢?它从哪里获取信息!?
答案1
对于这个答案,我假设可能有几个因素在努力调整你的时间。因为我真的不想胡乱猜测哪一个对你不利,我会尽力给你一个答案,这应该可以帮助你自己找到它。
在 UNIX 系统上,通常可以使用系统调用来设置时钟stime
。随着事情的发展,使用调用来更准确地设置时钟也成为可能clock_settime
。你也可能会遇到settimeofday
。在date --set
CentOS 机器上运行时,strace
显示它使用clock_settime
.
知道这一点后,解决方案就是跟踪这些系统调用。好消息是,Linux 有一个机制:debugfs。在我的系统上,调用mount
,我可以看到该功能可在以下位置找到/sys/kernel/debug
:
$ mount
none on /sys/kernel/debug type debugfs (rw)
...
然而,在某些系统上(包括 RedHat 和可能的 CentOS),它没有在启动时安装。因此你需要运行...
# mount -t debugfs nodev /sys/kernel/debug
另请注意,如果您在安装之前位于该目录中,则可能需要退出并返回才能在其中开始出现文件。
现在我们准备出发了。让我们启用系统调用的跟踪。我正在追踪所有这些,因为我真的不想检查哪一个正在被真正使用。可以在 中设置系统调用的跟踪/sys/kernel/debug/tracing/events/syscalls
。在此目录中,您应该找到...
sys_enter_stime
sys_enter_clock_settime
sys_enter_settimeofday
...取决于您的系统上可用的内容。
这些对应的事件进入我们的系统调用,这就是我们想要跟踪的内容(您还将找到sys_exit_*
目录)。在每个目录中,您将找到一个名为 的文件enable
,其内容应显示为 0。要跟踪这些调用,请将其设置为 1:
# echo 1 > /sys/kernel/debug/tracing/events/syscalls/sys_enter_stime/enable
# echo 1 > /sys/kernel/debug/tracing/events/syscalls/sys_enter_clock_settime/enable
# echo 1 > /sys/kernel/debug/tracing/events/syscalls/sys_enter_settimeofday/enable
现在我们已经设置了陷阱,只需等待某些东西将您的时间设置为正确的值即可。一旦发生,请运行以下位置的跟踪日志:
# cat /sys/kernel/debug/tracing/trace
现在,除非发生错误,否则您应该看到以下行之一:
stime-xxxxx [xxx] .... x.x: sys_stime(...)
clock_settime-xxxxx [xxx] .... x.x: sys_clock_settime(...)
settimeofday-xxxxx [xxx] .... x.x: sys_settimeofday(...)
紧随其后的数字stime-
(或另一个调用的名称)是进行系统调用的进程的 PID。现在去获取它:
# ps -fp xxxxx
UID PID PPID C STIME TTY TIME CMD
root XXXXX XXXXX 0 hh:mm ? hh:mm:ss time_warrior
您现在应该拥有确保系统停止获得正确时间所需的一切。最简单的事情可能是终止该进程,并确保它不会在启动时生成;当然,您必须确保它不会提供更多服务重要的这样做之前的目的:你不想让你的系统完全崩溃......
还记得在完成后通过向我们之前编辑的文件写入 0 来禁用跟踪。捷径可能是:
# echo 0 > /sys/kernel/debug/tracing/events/syscalls/enable
(该文件充当主开关对于所有其他人;它允许您关闭所有系统调用跟踪)
笔记:正如马克·普洛特尼克(Mark Plotnick)在评论中所说,这systemtap
可能是实现类似结果的稍微更容易的方法。stap
如果他愿意的话,我会让他写一个答案,因为我stap
根本不熟悉脚本。
答案2
如果你有系统水龙头安装后(这可能是 CentOS 系统上的情况),很容易跟踪系统范围内的任何系统调用。
# cat clock.stp
probe nd_syscall.stime, nd_syscall.settimeofday, nd_syscall.clock_settime {
printf("process %d (%s) called %s(%s) at %d\n", pid(), execname(), name, argstr,
gettimeofday_us());
}
# stap clock.stp
要测试这一点,请在另一个窗口中运行
# date 04301056
Thu Apr 30 10:56:00 EDT 2015
stap 的输出将是
process 7520 (date) called clock_settime(CLOCK_REALTIME, [1430405760.000000000]) at 1430405782997282