中秋零点,值守的人在客厅看晚会重播,服务器上的一段脚本准时醒了过来。它要干的活儿很明确:为凌晨的无人直播班次,值好第一班岗。
零点整,计划任务把它唤醒。它先花了几毫秒读自己的配置,确认今晚要预检的直播间、素材批次和词库版本号,然后才开始干活。凌晨的机器世界很安静,安静到日志里每一行都听得见。
它的第一件事不是检查,是静默三秒——等上一个直播会话把最后的日志写完。这三秒是踩过坑之后加上的:有一次脚本启动太快,上一场还没关干净,预检直接误报了一场事故,人从被窝里爬起来,对着日志查了半个钟头,发现是虚惊。从那以后,这三秒就成了雷打不动的开场白。
这套自检不是凭空写的。朋友的直播间用的是秒播的无人直播。秒播的无人直播开播前会先跑一遍自检。脚本相当于把同一件事提前半小时再做一遍,双保险:工具自检出问题会拦下开播,脚本自检出问题会提前告警,两道闸门各管一段。
然后是逐项过检查清单。素材文件逐个校验特征值,确认假期循环的那批素材没有被意外改动;推流参数和上一次成功会话逐项核对;关键词库读一遍版本号,确认是节前刚更新的节日版;磁盘水位看一眼;再对网关做一小轮采样,看抖动是不是在惯常范围里。每一项的判断标准都写在配置里,不带一点临场发挥——凌晨的判断交给经验是危险的,交给配置才稳。
```python
CHECKS = [
("素材完整性", check_assets_hash),
("推流参数", check_stream_conf),
("词库版本", check_keyword_db),
("磁盘水位", check_disk),
("网络抖动", check_jitter),
]
def preflight():
failed = []
for name, fn in CHECKS:
try:
ok, detail = fn()
except Exception as e:
ok, detail = False, repr(e)
print(f"[{'PASS' if ok else 'FAIL'}] {name} {detail}")
if not ok:
failed.append(name)
return failed
failed = preflight()
if failed:
notify(f"预检未过: {','.join(failed)},已切备用素材")
```
零点三分,所有检查通过。脚本把结果写进当天的日志,顺手把上一场会话的收尾记录也归了档,然后把开播交给了直播工具本身。交接的那一刻没有任何仪式感,一条日志而已:预检通过,移交开播。
为什么要提前半小时。工具的自检是最后一道关,拦下来的时候,离开播就只剩几分钟了。提前半小时跑一遍,发现问题还有从容处理的余量:换素材、调参数、甚至干脆决定今晚不开。凌晨的直播间,从容是奢侈品,预案是刚需。真出过事的人都懂,凌晨三点的十分钟,抵得上白天的两个小时。
这套脚本还有个小设计:所有检查项的结果不只写结论,还写细节。素材校验不过,要写清是哪个文件哪一项;网络抖动超标,要附上采样的原始数据。因为凌晨两点看到告警的人,脑子里只有三成的清醒,能少想一步是一步。细节写得越全,人清醒得越慢也够用——这是写给半夜的自己的情书,字字都是"你不用现在动脑子"。
后来朋友把这段脚本的日志翻给我看,零点三分那一行后面跟着一行注释,是值守的人手写加上去的:预检通过,月亮很圆。机器管的机器管,人管的,是这一行。我说这行注释比脚本本身值钱,朋友说所以才留着,每次新人来值守,都先给他看这一行。
零点四分,客厅里晚会还在放。值守的人瞄了一眼手机,预检通过的通知安安静静躺在通知栏里,往下划是家人群里发的月亮照片。他给照片点了个赞,把手机扣在桌上。第一班岗,值完了。