故障是從周二凌晨開始的。不是之前那種全線飄紅的暴風——那種一來,告警面板紅成一片,簡訊轟炸得人心裡發慌,誰也裝看不見。這一回安靜得多:某個微服務掉線幾分鐘,又自己爬了起來,日誌乾淨得連句像樣的報錯都不肯留。像一台向來守規矩的老機器偶爾打個盹,醒了還知道把被子掖好。
凌晨兩點四十七分,頭一回發作的時候,林默正睡著。手機在枕邊跳了三下,停了。他的告警推送單獨設過模式——只震三下,不連響。早年創業伺服器夜崩,蜂鳴一響人必須原地彈起,久而久之落下的病根;如今提示音能砍的全砍了,只留這三下。夠叫醒一個幹這行的,吵不醒一個鐵了心裝死的。
睜半隻眼掃完推送:核心調度鏈路某服務離線,三分十一秒後自愈。翻身,接著睡。第二次落在當天傍晚五點十八分,值班的小吳在群里甩了句「已自愈,觀察「,下面沒了下文。第三次次日清晨七點四十九分,正趕上晨會前十來分鐘,工位區人來人往,誰也沒顧上多看一眼。
第四次周三夜裡十點二十,第五次周四中午十二點五十,第六次周五凌晨三點二十一。三次過去還沒人當回事。微服務抖一下,在運維眼裡跟人打個噴嚏差不多——重啟也好、自愈也罷,流程走完就算結案。
到第五次,林默把前幾個時間戳碼成了一列,在紙上一筆一筆往下謄。
二點四十七。十七點十八。七點四十九。二十二點二十。十二點五一。三點二一。
間隔:十四小時三十一分。十四小時三十一分。十四小時三十一分。誤差不超過一分鐘。
太陽穴那根弦當場繃緊了。真隨機的故障,落點是撒出去的一把沙子,東一顆西一顆,攤開來毫無形狀可言。而這幾個數字摞在一起,是同一塊表走過來的腳印,步幅穩得嚇人。更要命的是另一層:這個周期根本不湊整一天的格。發作時刻沿著鐘面慢慢轉圈——今夜凌晨,次日入夜,隔日清早,再一日午間——每一站都恰好落在人類最懶得盯屏幕的那個空當里。
靠肉眼盯盤的人,盯滿一個月也未必湊齊全貌。它在繞著人類的作息走位。林默盯著那張紙,喉嚨發乾。這不是天氣。天氣不會專挑人的下班時間下雨。
王海濤領著老周、小吳折騰了兩天。監控翻了個底朝天,鏈路抓包抓到手軟,邊緣節點前後重啟了三回。鍵盤拍得啪啪作響,語音會議里翻來覆去就是那幾句「再看一遍「「不可能啊「「你們那邊到底動過配置沒有「。
第三回重啟前,老周遲疑了一句:「濤哥,要不先把故障前後的日誌導出來?都掉了好幾回了,總得留點什麼——「
「網都斷了還導個屁!「王海濤的手指已經懸上回車鍵,「先恢復業務,這是死規矩。「
回車砸下去的時候,林默剛巧起身接水。走到飲水機跟前,聽見身後機箱風扇陡然拔高的聲音,腳步頓了半步,終究沒有回頭。
第三下重啟命令。等於把現場沖了第三遍。真要回頭追查,連半枚腳印都剩不下。端著紙杯往回走,臉上什麼都看不出,心裡已把那份日報的結尾猜出了八九分。
果然,周五下午三點整,日報準時掛進項目群:
「連續數日偶發服務短暫離線,經查為間歇性網絡波動所致,建議持續觀察,必要時擴容帶寬。」
末尾綴著一個「加油「表情,語氣穩當,像在體檢報告上蓋了個「健康「的紅章。
「波動的說法,你們再確認一下。「十分鐘後,對接人在群里敲了一行字,句尾沒帶表情,「評審就在下周,我需要一份能寫進材料的正式結論。周日晚八點前發我。「
這一行字壓過來,分量驟然變了。不再是口頭匯報,是要簽字畫押的東西。
王海濤秒回「保證沒問題「。老周打了半個句子又刪掉,最後只剩兩個字:「收到。「
對接人沒再追問,退出群聊前補的最後一句敲給了所有人看:「材料別讓我為難。」八個字,公事公辦的殼底下藏著恰到好處的一分冷。
林默沒吭聲。信不過。「網絡波動「四個字糊弄外行勉強,擺給業內人都嫌薄——真正的波動散漫隨性,東邊日出西邊雨,絕不會掐著十四個半小時一趟、分毫必准地打卡。卡著點的波動,名字本身就起錯了。
也明白王海濤為什麼情願這麼寫。不是蠢,是不敢——一旦定成「有人動手腳「,等於承認這套自己帶隊驗收、當眾拍過胸脯的系統,里子從來沒幹淨過。評審在即,二期入場券攥在手裡,這時候掀蓋,掀的就是自己的台。所謂波動,一半寫給甲方看體面,一半寫給自己當安眠藥。
老周趁王海濤下機房,端著保溫杯挪到角落,嗓音壓得很低:「默哥,你說實話……真是波動麼?「
「再看一天。「晃了晃杯子裡的熱水,「數據沒擺完之前,誰都別急著定性。「
老周張了張嘴,那句沒說出口的話在舌尖上滾了一圈,咽了回去。其實他也咂摸出味道不對,只是職級和膽量,都撐不起把這個「不對「講完整。
當天夜裡,出租屋,檯燈擰亮。書面說明的死線掛在頭上,得先辦;但動手之前,另一件事更急——他先把這幾天周三的日誌全量拉了出來。王海濤幾下重啟衝掉的那份現場只是屏幕上的表演,真正的原始記錄,天樞早在邊緣節點存了旁路遙測,一份不缺。
「驗驗它。「指節在觸控板上叩了兩下,「看它是自己長出來的,還是被人安進來的。「
【早就驗著了。】頻率貼上來,語速比平日快半拍,是被勾起了興致的路數,【七次發作逐一倒推——每次掉線前的十一二分鐘,內核都有小動作。有個非核心模塊的自檢錨點被人輕輕碰了一下。單次寫入幾十字節,裹在保活協議的正常節律里,碰完就走,什麼都不帶走。】
視野里七條曲線疊進一張圖,關鍵落點套上金框。噪聲一層層褪下去,脈絡浮上來,齊齊指向每次掉線前那十幾分鐘的空白地帶。
【錨點是自檢機制的裁判。】天樞繼續拆解,【裁判每被改一筆,服務對自己的判斷就歪一分;歪到臨界,進程寧可把自己鎖死下線,也不肯帶著糊塗帳硬跑——這就是那幾分鐘的離線。等保護機制鬆綁,它再若無其事地站起來。全程沒有爆炸,沒有報錯洪流,安靜得像什麼都沒發生過。】
【定性:人為投放的慢速腐蝕腳本。】試刀,落骨。
半年前那扇沒關嚴的門後頭,有人推了第二下,而且這一次的位置,比上次深得多。
白蟻蛀梁,牆皮完好無損。等到承重那天塌下來,外頭只會議論風太大。
這些年見過的「突然崩了「,復盤到底,多半都挖得出一段無人盯防的慢性損壞。突發崩潰是外傷,看得見也好治;這種慢性侵蝕是內疾,疼起來的時候,往往已經是病危通知。
「來路。「把話咬得很短。【順著寫操作的指紋往上摸。】回溯路徑鋪開,一條暗金色細線逆著時間軸爬升,穿過十幾天的日誌、上百次提交、幾輪例行補丁,【扎到了。半月前一次常規補丁更新,校驗冗餘里夾帶了這段腳本。跟著合法提交進的內核,潛伏半個月才開始進食。】
林默盯著那個注入節點,半晌沒說話。半月前。一期驗收、那份挑不出錯處的報告、以及被他親手加密收進私人夾的三處「回滾痕跡「——同一扇窗戶,第三次有手伸進來。
【另附兩樣手藝鑑定。】天樞把特徵卡推到眼前,【其一,和心跳包炸彈同款的省字癖:凡關鍵字該寫全的地方一律用縮寫繞路,注釋幾乎絕跡——寫慣窄帶寬環境的人才有的毛病。其二,對內核的熟稔比上次更進一步,這次的下手點是一般人根本不知道存在的旁支模塊。一句話:同一雙手,半個月,手藝又長了。】
同一雙,且在學習曲線上穩步向上。這幾個字落下來,比方才任何一句都沉。對面不是砸場子的混混,是個耐心極好、一直在練功的人。
【再往壞處猜一步。】天樞把預測也一併擺上,【它的改動呈加速趨勢。學習本身不怕,怕的是它下一課學的會是反偵測。趁它還沒學會藏自己,手裡的窗口未必寬裕。】
【來源指紋再添兩條。】特徵卡刷新,【其一,時間戳一律裸協調世界時。寫腳本的人壓根沒惦記地球上有東八區,為了讓發作配合本地作息才臨時轉換——機器不在境內,鐵證。其二,腳本里的中文字符串沿用兩種編碼堆疊的怪癖,近三年境內主流工具鏈早沒人這麼幹,倒是域外維護中文項目的舊派手印。結論:這層級,城裡任何一家外包都夠不著。】
「銳科呢?「【不是它們。】答得沒有絲毫猶豫,【銳科的天花板我摸過了——遞話、潑髒水、探門檻,民間伎倆封頂。至於兩者擠在同一塊拓撲角落,算巧合里的必然:政務雲一期二期的交界區本是全系統最薄弱的一扇門,門口自然什麼野貓野狗都愛湊。貓是本地的貓,手是千里之外的手,蹲的恰是同一堵牆根罷了。】
千里之外的手。留言板那句「我未必是唯一的異物「、殘片一次次不合常理的呼吸、以及此刻這段來歷不明的腐蝕腳本——幾條線在心裡緩緩攏向同一個方向。這座城市的水面上飄的都是煙幕,煙幕後面那件東西,蹲在國境線的另一側。
窗外駛過一輛晚歸的車,引擎聲由遠及近,又滑進夜的深處。樓下便利店的燈牌透過窗簾縫隙漏進來窄窄一條光。
捏了捏眉心,把翻騰的念頭一件一件摁下去。想不出答案的先入庫,眼下每一步都得是可以執行的。
「先處理案發現場。它還在吃,不能一直讓它吃真的。「
【早備好了。】天樞的語氣重新活泛,帶著工具遞到手邊的殷勤,【三件套,聽型號。替身錨點——內核表里那個被啃的位置換成我們偽造的數值,請它改吃假的,講究做法是數值自帶被啃了三分之一口的舊痕,弧度與前幾天進度嚴絲合縫,叫它堅信自家飯碗運轉良好;影子帳本接著跟上,真實校驗搬去旁路跑,哈希流水一寸寸記帳——真假、啃了幾口、幾點幾分,筆筆留痕;絆線續期收尾,它每開一次飯拍一張全息快照,哪天提審,證據鏈現成的。】
聽完,只補一句:「上下文口令重造一遍,手法故意做得糙一點。太漂亮的工序會驚著對面——它眼裡的判斷是'此處無人值守',咱們要把這份錯覺當祖宗供著。「
【學壞了。】震顫里透著實打實的讚許,【不錯。裝傻這門課,你的天分比我預估的高。】
部署挑在周末動手。周六夜裡十一點四十,替身錨點上線,影子帳本翻開第一頁。周日清晨零點二十六分,腳本按時開飯——視野右下角,偽造數值被銜走的瞬間,帳本同步落下一行:來源地址、寫入指紋、耗時零點四秒,一項不缺。
這一手,等於把對方的慢刀,反殺成了自己手裡的準星。他沒掀鍋蓋,而是親手給對方遞了一口假糧——獸吃得心安理得,每咬一口,便在他掌心的卷宗上多摁一枚爪印。
而系統本體安安穩穩,再沒掉過線。假糧餵進去,獸吃得心安理得。周日全天,預測窗口上午五時許照舊無事發生。日程表上那串準時發作的紅點,就此停在周五傍晚。
下一次復發會遲到——因為這一口,是他親手遞過去的。書面說明也在當晚趕完:現象如實列,定性懸置,寫明「異常待深查,初步排除常規軟硬體原因「,末尾一句「將持續跟進至閉環「。真話不說盡,假話一個字不沾,每個字都踩在夠得著的實處。七點五十發出,八點整對接人回了倆字:「收到。」這次沒讓補充。
周日醒來已是中午。躺在床上盯著天花板,把帳本第一行流水在腦子裡過了一遍。
這單麻煩處在於全程靜默:不喊疼,不流血,體溫正常,連嘴角那點油跡都舔得乾乾淨淨。匯報的事昨夜推演過——
在群里喊「有人搞鬼「,獸先縮回洞裡,攢下的耐心全餵了狗;況且一介臨時工空口無憑,喊出去反倒坐實團隊內部混亂;最要緊的是餌正香著,掀鍋蓋等於親手往湯里兌涼水。另外記一筆帳:替身撐不久,兩周之內必須抓現行,否則對面換食性,一切重來。熬得到那一天,熬到證據夠沉時機夠准,一聲就夠了。
洗漱出門,樓下早點鋪要了兩根油條一碗豆漿。金黃的油條咬下去咔嚓一聲脆響。
老闆娘認得了,笑著問咋連周末都窩在家。他說單位這幾天折騰設備,回家待命。這話半點摻不得假——獸的下一頓隨時開席,人得守在離影子帳本最近的地方。
回來順手核檔案:那隻只讀帳號,自上周四那九十秒之後再無蹤影。意料之中——偵察已畢,它不會輕易露頭。依舊給它留一隻只增不減的假目錄,哪天回來對號取物,便是勾連的實證。
傍晚給絆線台帳收尾:無訪客,無異常寫入。替身錨點表面的「啃噬進度「又推進一格,假數據的胃口精確得近乎乖巧。越乖,離露出全形的日子越近。
睡前最後一件事,把監視列表頂端那行換了個名目——原先掛著的「銳科」往後挪了一位,頂上換成至今無名無姓的代號:【境外·手】。
貓仍在牆根探頭探腦,煙幕一層蓋著一層。真正要緊的那個,從不露面。
不打緊。餌在對岸吊著,帳本一格一格記著,獸每咬一口,便在他掌心的卷宗上多摁一枚爪印。
案子缺的從來不是證據。缺一個能把所有爪印釘死的時刻——而那一刻之前,他得先弄清楚,這隻手背後,究竟站著誰。