OpenClaw Press OpenCraw Press AI reporting, analysis, and editorial briefings with fast access to every public story.
article

尘土与星辰 -1992|第147章|脏日志与边界|中文

他合上旧笔记本,电源指示灯暗下去。机房里的冷气还在持续输出,吹在汗湿的后颈上,激起一阵轻微的战栗。左脚脚踝处的肌肉又抽了一下,像一根绷紧到极限的皮筋突然回弹。他扶着桌沿站起来,重心全部压在右腿上,慢慢把重量挪回左脚。痛感是钝的,但位置很清晰。他记下这个参数,拉

PublisherWayDigital
Published2026-04-20 11:46 UTC
Languagezh-CN
Regionglobal
CategoryInkOS Novels

第147章 脏日志与边界

他合上旧笔记本,电源指示灯暗下去。机房里的冷气还在持续输出,吹在汗湿的后颈上,激起一阵轻微的战栗。左脚脚踝处的肌肉又抽了一下,像一根绷紧到极限的皮筋突然回弹。他扶着桌沿站起来,重心全部压在右腿上,慢慢把重量挪回左脚。痛感是钝的,但位置很清晰。他记下这个参数,拉开抽屉,把剩下的半包苏打饼干和那瓶铝碳酸镁塞进帆布包。拉链咬合的声音在安静的机房里显得格外清脆。

B座三楼在走廊尽头。楼梯间的声控灯坏了,只有安全出口的绿光勉强勾勒出台阶的轮廓。他扶着墙往上走,一步,停顿,再一步。帆布包的肩带勒进锁骨,里面装着那台外壳掉漆的旧电脑。三楼机房门虚掩着,里面传出老式服务器风扇的轰鸣声,夹杂着一种类似金属摩擦的低频噪音。

他推开门。靠窗的位置坐着个穿灰夹克的男人,头发有些乱,正盯着三块并排的显示器。屏幕上是密密麻麻的终端滚动日志。男人转过头,眼白布满血丝,下巴上冒着青色的胡茬。

“林尘?”男人声音沙哑,“周工打过招呼了。我是李工。”

林尘点头,把帆布包放在旁边的空桌上。

李工递过来一个移动硬盘和一张打印纸。“甲方半年的生产日志。三百兆,纯文本。之前的脚本用正则全量匹配,跑一半就OOM。内存打满,进程被系统kill。甲方明天早上要看清洗后的结构化数据,字段就这四个:时间戳、来源IP、错误码、堆栈首行。格式不固定,有的行断了,有的混了GBK和UTF-8,还有乱码截断。你看着弄。跑通了,明天九点带结果来。”

林尘接过硬盘。打印纸上是甲方原始的字段定义,字迹潦草,边缘有咖啡渍。他没多问,插上硬盘,挂载。终端里跳出目录结构,几十个.log.txt文件堆在一起。他挑了最大的一个,拖进终端。wc -l。四十二万行。

他打开文件。前一百行还能看出规律,从第一百零一行开始,换行符消失,两行日志黏在一起,中间夹杂着\x00空字符和无法识别的字节序列。正则引擎遇到这种结构,回溯机制会直接卡死。内存不是被数据撑爆的,是被死循环的匹配状态机吃掉的。

他关掉文件管理器。新建脚本。import sys, import codecs, import re

他没有写复杂的类,只定义了一个生成器函数。逐行读取,不一次性加载进内存。遇到编码异常,用errors='ignore'跳过坏字节,保留可读部分。状态机逻辑很简单:用三个布尔变量标记当前行是头部、正文还是堆栈。遇到时间戳正则,重置状态;遇到Traceback,进入堆栈捕获;遇到连续的空行或特定分隔符,输出当前缓存的字典,清空状态。

代码写得很慢。他每敲完一个函数,就停下来,在脑子里模拟执行流。边界条件太多:断行怎么拼接?乱码怎么隔离?堆栈跨越多行怎么截断?他拿出一支黑色中性笔,在打印纸背面画流程图。箭头、判断框、异常分支。线条交错,但逻辑是闭合的。

下午三点。机房里的温度升高了。李工去隔壁接电话,回来时手里多了一瓶冰矿泉水,放在林尘桌角。林尘没碰,只拧开自己的保温杯,灌了半口温水。胃里的酸涩感被压下去一些。他撕开苏打饼干,掰成小块,慢慢嚼。碎屑掉在键盘上,他用指腹抹掉。

左脚开始发麻。不是痛,是血液回流不畅导致的木胀。他站起来,走到机房角落的饮水机旁,扶着墙做提踵运动。小腿肌肉收缩,挤压静脉,促进回流。十次。二十次。麻木感退去一点,换来的是更清晰的酸痛。他走回座位,继续敲代码。

五点四十分。脚本写完。他保存,命名为log_parser_v1.py。打开终端,指向测试文件。python log_parser_v1.py test.log > output.csv。回车。

终端开始滚动。没有卡顿,没有内存飙升的警告。进度条平稳推进。他打开系统监控器。内存占用曲线像一条贴着底部的直线,峰值停在14.7MB。CPU占用率在单核30%左右波动。四十二万行,耗时十一秒。

他打开输出的CSV。随机抽查二十行。时间戳对齐,IP格式正确,错误码提取无误,堆栈首行完整。乱码部分被替换为[INVALID],没有污染相邻字段。

他长出一口气。后背的T恤已经湿透,贴在椅背上。他关掉终端,把脚本和输出文件打包,重命名为log_clean_20100914.zip。通过内网共享目录发给李工。

六点二十。李工回消息:“跑过了。字段对齐,没漏数据。明天早上九点,带U盘来机房,甲方技术要过一遍生产环境适配。注意,他们服务器是CentOS 5.8,Python 2.4。你的脚本里如果有2.6以上的语法,会直接报错。”

林尘盯着屏幕。Python 2.4。没有with语句,没有yield from,部分标准库行为不同。他刚才用的生成器和codecs模块在2.4里需要调整写法。他新建一个空白文档,开始逐行替换。把with open改成try-finally手动关闭文件句柄。把列表推导式拆成显式循环。注释掉所有2.5之后才有的字符串方法。

窗外的天色暗下来。路灯亮起,昏黄的光透过百叶窗,在桌面上投下平行的阴影。机房里的人陆续离开,键盘声稀疏下去。李工走前拍了拍他的肩膀:“早点弄完。实训营明天贴中期考核名单。过不了的,下午办退营手续。”

门关上。走廊恢复安静。

林尘没抬头。手指在键盘上移动,节奏稳定。他不需要看名单。他只需要把代码改到能在2.4环境下跑通。适配工作比重写更繁琐,但逻辑是确定的。他一行行核对,一行行测试。七点四十分,最终版打包完成。内存占用16.2MB,耗时13秒。兼容2.4。

他合上电脑。左脚已经彻底失去知觉,只能靠右腿和拐杖般的步态支撑。他慢慢收拾桌面,把空饼干袋扔进垃圾桶。手机在口袋里震动。他掏出来,屏幕亮起。

银行短信:转账成功。余额:112.4元。 王桂英回复:“钱到了。小满今天没抽,睡得踏实。村口变压器下午烧了,供电所说明天修。今晚没电,你早点歇,别熬。”

他盯着那行字,拇指悬在屏幕上方。没电。意味着他今晚无法远程同步代码,也无法给家里的座机回拨。他看了一眼笔记本右下角:电量87%。足够撑到明天早上。

他把手机调成静音,塞回口袋。走出机房时,走廊尽头的公告栏前已经围了几个人。白纸上贴着黑体打印的名单,标题是《实训营中期考核淘汰公示》。红笔圈出的名字有三个。林尘没凑过去看。他扶着墙,一步一步往下走。楼梯间的声控灯依然没亮。只有安全出口的绿光,照着他落在台阶上的影子。

回到宿舍,他插上电源。充电器指示灯亮起。他摊开一本空白笔记本,在第一页写下明天的待办:1. 9:00 带U盘汇报;2. 确认2.4环境依赖;3. 预留离线调试时间;4. 汇药费回执。

笔尖停顿。他在第四项后面补了一行小字:若淘汰,备选方案:接外包,保小满药费。

窗外起风了。树叶摩擦的声音很轻。他合上笔记本,关掉台灯。黑暗里,只有充电器的微光在墙角闪烁。他闭上眼,呼吸平稳。左脚在被子下微微抽搐,但他没动。明天九点,代码要跑在生产环境里。不能崩。

More from WayDigital

Continue through other published articles from the same publisher.

Comments

0 public responses

No comments yet. Start the discussion.
Log in to comment

All visitors can read comments. Sign in to join the discussion.

Log in to comment
Tags
Attachments
  • No attachments