第 14 章

数据疑云

冰晶形态不一致背后还藏着更深一层线索。

程默盯着屏幕上那片放大后的冰晶显微图像,指尖在触摸板上缓慢移动。窗外是浓稠的夜,雪暂时停了,只剩下风刮过金属外壁时发出的、永无止息的呜咽。房间里只有屏幕的光,映着他的脸,在墙壁上投出一个僵硬的轮廓。

他关掉图片窗口。桌面上是几个打开的日志文件:望远镜伺服系统日志、备用电源切换记录、主供电负载曲线。文字和数字挤满了屏幕,黑色的背景,白色的字符,密密麻麻像一片冻住的星河。

这些数据他之前看过,但那时是为了寻找“异常”。现在他需要的不再是孤立的异常点,而是将它们连接起来的逻辑链条——一个可以被精确计算出来的时间缝隙。

程默调出案发当晚的望远镜伺服系统归位程序日志。按照规定,大型望远镜在每次观测任务结束后,会执行自动归位程序:镜筒缓慢移向天顶方向并锁定,圆顶关闭,镜筒保护罩合拢。整个过程预设耗时8分30秒,从程序触发到完成,每一步都有毫秒级的时间戳记录。

他写了一个简单的脚本,用来比对预设时间线与实际执行时间线的偏差。脚本逐行读取日志,将每个动作的实际时间戳与理论时间戳相减,输出差值大于设定阈值(比如1秒)的记录。

服务器持续发出低频的嗡鸣。硬盘指示灯规律性地闪烁。

脚本运行了七分钟。输出列表里只有一条记录。

【23:41:22.337】 触发自动归位程序。
【23:49:52.419】 镜筒保护罩确认合拢。
【23:49:52.419】 程序结束。

预设的结束时间应该是23:49:52.000。这419毫秒的延迟在系统误差允许范围内,却依旧让程默感到一丝异样。他敲击键盘,调出更底层的伺服电机响应日志。一行行数据流快速滚动,他的目光迅速锁定在“镜筒轴向移动完成”和“保护罩驱动电机启动”两个连续事件之间。

这里有一个空档。

这里有一个空档。

预设流程里,镜筒移动到天顶锁定位置后,应立刻(间隔<100毫秒)触发保护罩合拢指令。但实际记录显示:【23:49:05.112】 镜筒轴向移动完成并锁定。【23:49:52.112】 保护罩驱动电机启动指令发出。

中间差了47秒。

47秒。程默向后靠进椅背,脊椎抵住坚硬的靠垫。这不是系统误差或网络延迟能解释的间隔。伺服电机的响应时间以毫秒计,指令队列是连续的。这47秒像是被插入的空白——或者更准确地说,像是某个外部指令暂停了自动流程,直到47秒后才释放。

他保存了这个时间点:23:49:05到23:49:52。这是第一个锚点。

接下来是备用电源切换记录。

案发当晚的主供电波动记录很模糊:【约23:46至23:49期间存在电压不稳现象,备用发电机启动以保障关键负载】。“约”这个字掩盖了精确性。但程默记得赵海峰证词里的细节:“我当时在主控室核对数据……大概十一点四十五分左右吧?听到发电机启动的声音……持续了大概两三分钟。”

大概十一点四十五分左右。

程默需要比“大概”更精确的东西。他登录到备用发电机控制子系统——这个系统独立于主控网络,有自己更精细的内部日志,通常只有设备维护工程师吴振会定期查看。权限验证通过得有些慢,进度条一点点往前爬。

门外的走廊里传来极轻微的脚步声。

程默的手指停在键盘上。脚步声由远及近,经过他门前时没有停顿,继续向前去了。是林远?还是其他人?他等了几秒,直到脚步声彻底消失在走廊尽头,才重新将注意力转回屏幕。

控制子系统的界面朴素,黑白表格。程默输入日期和时间范围:23:45:00到23:50:00。检索结果弹出:

【23:46:28.115】 主电失压检测触发(阈值低于198V持续500ms)。
【23:46:29.002】 备用发电机启动指令发出。
【23:46:31.448】 发电机转速达到标称值(1500rpm),输出接入切换开始。
【23:46:33.891】 输出切换完成(全部关键负载由发电机供电)。
【23:47:05.112】 主电恢复检测(电压稳定高于205V持续1s)。
【23:47:06.554】 发电机卸载指令发出。
【23:47:08.997】 输出切换回主电网完成。
【23:47:10.440】 发电机停机指令发出。
【23:47:14.203】 发电机完全停止运转。

精确到毫秒的时间戳链。

程默快速心算:从发电机启动指令发出(23:46:29)到完全停止(23:47:14),整个备用电源介入周期持续了四十五秒多一点。但这还不是全部——关键负载切换实际发生在23:46:33到23:47:08之间?不对。他重新读了一遍:输出切换完成是在33.891秒时全部关键负载已经切到了发电机;而切回主电网是在08.997秒完成的。也就是说,在33.891到08.997这三十五秒多的时间里,整个观测站的关键系统——包括主控室服务器、望远镜伺服控制、圆顶驱动——都由备用发电机供电。

程默快速心算:从发电机启动指令发出(23:46:29)到完全停止(23:47:14),整个备用电源介入周期持续了45秒多一点。但这还不是全部——关键负载切换实际发生在23:46:33到23:47:08之间?不对。他重新读了一遍:输出切换完成是在33.891秒时全部关键负载已经切到了发电机;而切回主电网是在08.997秒完成的。也就是说,在33.891到08.997这35秒多的时间里整个观测站的关键系统——包括主控室服务器、望远镜伺服控制、圆顶驱动——都由备用发电机供电。

而发电机会带来什么?赵海峰说过:“……可能导致局部网络暂时失步或数据传输中断。”林远也提到过:“……那几天基站信号不稳。”

独立供电的系统时钟可能发生微小偏移?程默的目光落回那个数字:35.106秒(08.997减33.891)。这是第二个锚点区间:一个理论上可能造成内部时间基准暂时“失步”的窗口。

但直觉告诉他,这两个事件的关联绝非巧合。问题在于如何定义它们重叠的部分——那才是真正的、可能被利用的“无人见证窗口”。

他把两个时间区间列出来:

望远镜归位流程被插入的47秒暂停:从 A_start = 23:49:05.112 (镜筒锁定)到 A_end = 23:49:52.112 (保护罩驱动启动)。

备用发电机为关键负载独立供电的窗口:从 B_start = 23:46:33.891 (切换完成)到 B_end = 23:47:08.997 (切回主电完成)。

表面上看,A区间开始于23:49分之后,而B区间在23:47分就已结束——两者似乎没有交集?程默皱起眉。不对。

他调出全站主时钟同步日志。案发当晚的记录显示:【23:46:30至23:47:15期间部分子系统时钟同步请求超时/失败】——正是备用发电机运行期间!而且失败列表里包括了“望远镜伺服控制单元”。

一个念头猛地刺入脑海:如果望远镜伺服控制单元的时钟在那一刻发生了偏移呢?如果它的内部计时在那35秒里变慢了、或者变快了?

那么它记录下的所有时间戳——包括那个“镜筒锁定”的时间戳A_start=23:49:05.112——就可能不是真实的绝对时间!它记录的可能是自己那个暂时失步的本地时钟所认为的时间!

程默深吸一口气,手指开始快速敲击键盘。他需要找到一种方法来校准或推断这种偏移的可能幅度和方向。

首先得确定一个基准点。在全站范围内有什么事件是所有系统都必然记录、且时间戳应该一致的?他想到了圆顶控制开关的记录——圆顶开启和关闭会触发物理限位传感器信号并记入日志系统;这个信号路径与伺服控制系统不同理论上会更独立可靠一些?

他查案发当晚圆顶关闭的记录:【根据气象条件及观测计划结束,圆顶于22:15关闭,后未再开启,直至次日例行检查】。也就是说,当晚圆顶一直关着?但这和师兄坠崖的平台位置矛盾……等等,不对,师兄是在室外观测平台出事的,而平台在圆顶之外,圆顶关不关闭不影响平台……

思路卡住了几秒钟后,程默摇了摇头,放弃从圆顶寻找基准点,转向另一个思路。既然偏移发生在B区间内,那么只要找出望远镜伺服系统在B区间前后记录的其他事件,并与主系统记录进行比对,就能推算出偏移量?

他检索伺服系统日志,寻找在B区间前后发生的其他可识别事件,很快找到了一个:【22:30,例行伺服自检完成】。这个事件在主控服务器日志里也有对应条目:【22:30,伺服自检报告接收确认】。两者时间戳完全一致,都是22:30:00整。这说明至少在22:30时,伺服系统的时钟还是同步的,偏移还没发生。那么,偏移只可能发生在22:30之后,且在A事件之前?

范围缩小了,但还不够精确。程默继续翻找,忽然注意到一条平时很容易忽略的记录:【每日23时整,伺服控制系统会向主时钟服务器发送一次静默校时请求,但不强制等待回应;若超时,则使用本地时钟继续运行】。

案发当晚的这条校时请求,发送时间记录为:【22:59:59.998】(伺服系统日志)。而主时钟服务器接收到的请求时间戳为:【22:59:59.997】(服务器日志)。相差仅1毫秒,正常。这说明在接近23点时,时钟仍然基本同步?

但紧接着,下一条相关记录来自主时钟服务器:【对伺服控制单元的校时响应,因网络延迟,于00:00:03.112送达,但该单元未返回确认,推测其已进入某种待机或非响应状态】。

送达时间是午夜00:00:03.112?这不对,那天晚上师兄出事是在接近午夜,但具体……程默迅速调出简易调查报告里的估计死亡时间:【根据体表温度及环境条件推测,死亡时间介于23:45至00:15之间】。

而伺服控制系统在接近午夜时分处于“非响应状态”?结合之前发现的校时请求超时……

程默感到太阳穴微微抽痛。所有碎片都在这里,但它们需要一种正确的拼法。他闭上眼睛,让眼前的数据流暂时暗下去,耳边只有服务器风扇持续的嗡嗡声。

然后他重新睁开眼,目光落在两个原始区间上:A_start=23:49:05.112(伺服系统记录的“镜筒锁定”),和B_start=23:46:33.891(发电机供电开始)。

假设——只是假设——伺服系统的时钟在B区间内,因为独立供电和网络失步而发生了向前偏移,即它的时钟变快了。那么,它记录的A_start=23:49:05.112对应的真实绝对时间就会比这个数字更晚!

反过来,如果它的时钟变慢了,那么真实绝对时间就会更早!

哪种情况更合理?发电机供电期间网络中断,本地时钟缺乏同步源,通常会导致本地计时晶体自由运行。而自由运行的晶体由于温度、电压等微小因素,其频率并非绝对稳定,可能略快或略慢于标称值。但考虑到当时情况……程默回想起吴振闲聊时提过的一件事:“咱们那批老伺服控制箱里的计时晶体有点小毛病,温度低的时候容易偏快个几十ppm……”

哪种情况更合理?发电机供电期间,网络中断,本地时钟缺乏同步源,通常会导致本地计时晶体自由运行。而自由运行的晶体由于温度、电压等微小因素,其频率并非绝对稳定,可能略快或略慢于标称值。但考虑到当时情况…………程默回想起吴振闲聊时提过的一件事:“咱们那批老伺服控制箱里的计时晶体有点小毛病温度低的时候容易偏快个几十ppm……”

温度低那天晚上室外零下二十度室内即便有暖气控制柜所在的技术层温度也不会太高所以偏快的可能性更大!

如果偏快,假设偏移量为ΔT(未知正数),那么真实绝对时间T_real与伺服记录时间T_servo之间的关系就是T_real = T_servo - ΔT。因为伺服时钟走快了,所以它记录的时间比真实时间“晚”了ΔT。换句话说,当它显示是某个时刻时,真实世界其实还没到那个时刻!

程默用笔尖敲了敲桌面,将这个关系代入。那么,A_start的真实绝对时间就是:
T_real_A_start = A_start - ΔT = 23:49:05.112 - ΔT。

同理,A_end的真实绝对时间是:
T_real_A_end = A_end - ΔT。ΔT可能在整个短窗口内变化,但作为初步估算,可以假设它基本恒定。

他停下笔,深吸了一口气。现在关键来了:要让这个被延迟了47秒的保护罩启动事件,与发电机供电窗口产生重叠,必须满足——

T_real_A_start < B_end,且 T_real_A_end > B_start。

T_real_A_start<B_end且T_real_A_end>B_start

即真实版本的A区间与B区间存在交集

代入不等式:

(1) T_real_A_start<B_end => (A_start-ΔT)<B_end, => ΔT>A_start-B_end
(2) T_real_A_end>B_start, => (A_end-ΔT)>B_start => ΔT<A_end-B_start。

计算一下数值:

程默将ΔT的数值范围代入不等式。A_start-B_end = 23:49:05.112 - 23:50:25.891 = -80.779秒。这意味着ΔT > -80.779秒,这个条件几乎总是成立。关键在于第二个不等式:ΔT < A_end - B_start。A_end是伺服记录的保护罩动作结束时间,他需要从日志里找到它。他快速检索,找到了对应条目:A_end = 23:53:57.445。那么,A_end - B_start = 23:53:57.445 - 23:46:33.891 = 443.554秒,约7分23秒。

所以,只要伺服时钟的累计正向偏移量ΔT小于443.554秒,真实发生的保护罩启动事件,就会与发电机供电的“空白窗口”产生重叠。考虑到吴振提到的“几十ppm”(百万分之几十)的偏移率,在短短几分钟内积累起数分钟偏移的可能性微乎其微,但并非绝对不可能,尤其是在极端低温下晶体频率可能发生更剧烈的瞬变。然而,这已经为“重叠”提供了理论上的狭窄通道。更重要的是,这ΔT的取值范围,与伺服系统在午夜00:00:03.112那次“未返回确认”的异常状态,隐隐指向同一种可能性:那个伺服控制单元的计时系统,在当晚确实出了问题。

数据似乎正在拼凑成形,但程默感到的并非豁然开朗,而是更深的寒意。这寒意不仅来自屏幕上那个被计算出的、可能存在的“时间缝隙”,更来自一种无形的阻力。他决定验证最后一个环节:圆顶的监控。如果凶手利用了那个窗口,圆顶内部监控或许没有直接记录,但监控系统自身的底层存储和访问日志,或许会留下别的痕迹。

他利用自己的工程师权限,尝试访问监控系统的非循环存储区,那里通常保留着系统日志和异常访问记录。查询命令执行了片刻,返回结果。然而,在案发当晚及随后几天的日志中,他注意到数条指向圆顶监控存储块的访问记录,标记的权限账户是“admin_zh”,访问时间集中在案发次日凌晨02:17至02:35之间。那是赵海峰站长的最高权限账户。记录显示,这些访问执行了“日志查看”和“元数据检索”操作,但没有显示具体查看了哪些视频流。时间太巧合了。站长在事故初步调查开始前,就独自、深夜调阅过监控底层数据。

程默靠在椅背上,屏幕的幽光映着他紧绷的脸。伺服时钟的可能偏移,勾勒出一个理论上可行的作案窗口;供电日志与望远镜记录,提供了交叉验证的锚点;而现在,最高权限账户在案发后不久对监控数据的悄然检视,像一块沉重的拼图,咔哒一声嵌入了某个他不愿面对的位置。

他掌握了越来越确凿的、关于“时间如何被利用”的证据,但凶手的影子,却似乎随着证据的清晰,投向了那个他此前未曾深究、或者说,下意识避开的方位——那个拥有全站最高权限,在事故报告和询问中提供了一锤定音般“完美”证词,并且始终沉默地笼罩在一切之上的身影:赵海峰。

窗外的暴雪似乎永无止息,封山期的孤立感从未如此具体。数据海洋浩瀚而嘈杂,充满了日常操作的无意义噪音,而他要寻找的,是凶手精心隐藏在时间缝隙里的那一丝异常涟漪。与此同时,另一种感知渐渐清晰:他并非在与虚无的谜题对抗,而是在与一股试图抚平所有褶皱、掩盖所有痕迹的无形力量对抗。这力量可能来自某个具体的人,也可能已经渗透进这座观测站寂静的墙壁里。

他关掉了复杂的计算界面,清空屏幕。然后,他拿起笔,在笔记本崭新的一页上,缓缓写下了三个词:“时间窗口”、“权限痕迹”、“沉默的证词”。在最后一个词下方,他用力画了两道横线。

接下来,他需要从对“物”的调查,转向对“人”的观察。而首要的观察对象,此刻正与他同处这栋被风雪封锁的建筑之中,拥有着他难以企及的权限和威望。程默知道,自己必须更加谨慎,每一步都可能触发警报。他看了一眼时间,凌晨三点已过。他保存好所有数据,加密备份,然后清除了临时工作痕迹。疲惫如潮水般涌来,但大脑却异常清醒,某种冰冷的决心取代了之前的困惑与焦虑。他需要休息片刻,哪怕只是假寐,以应对即将到来的、更为危险的白天。