Perl 00:先冻结解释器,再约定合成日志
两台机器都说“运行 Perl”,却可能使用不同 patch、不同的系统补丁和不同的模块版本。把一段脚本跑通,不等于复现了同一条语言规则。这一篇先钉住运行对象和输入输出字节;后面每个上下文或编码结论,都要在这个坐标下解释。
课程导航 按原定主线 00–39、选修 E01–E08 的主题组织学习路径。2026-10-06 的实际文章编号与原定课程编号有差异,导航列出主题映射及补充专题。文章数量、实验通过和原定覆盖分别核对,不能互相代替。
先区分四种版本
2026-10-06 UTC,在此容器执行 perl -v 得到 5.38.2;readlink -f /usr/bin/perl 指回 /usr/bin/perl,它的 SHA-256 为 fa36b75b21e94f424b61aa058b743cc62c94e7fa45a085fdeffb2bae687ed925。系统包 perl-base 版本是 5.38.2-3.2ubuntu0.4。完整 perl -V 原文收在 examples/perl-language/evidence/perl-V.txt;该文件的 SHA-256 记录在 VERSIONS.md。
上游源码另有自己的身份:官方 perl-5.38.2.tar.gz.sha256 给出 a0a31534451eb7b83c7d6594a497543a54d488bc90ca00f5e34762577f40655e,实际从 CPAN 镜像读取完整包计算出的摘要相同。v5.38.2 的 Git 注释标签剥离后指向 55dd2f792ffc8cefe614350a411f785374281b24。实验阅读的官方文档是这个校验过的发行包中的 pod/*.pod,不是随网页更新的 latest。上游包的校验不能证明 Ubuntu 二进制直接由这个标签构建;后者的补丁清单和配置仍应以本机 perl -V 为准。构建参数中的 Linux 6.1.0 也不是本容器实际的 5.10.134 内核。
00 的运行基线只装载 Perl 随附的 Encode、Exporter、FindBin 等模块与测试模块;那时没有安装第三方 CPAN 包,不能借核心模块的存在冒充“隔离安装通过”。23 增量才在示例树内安装 Text::CSV 2.06,实测依赖和隔离证据见 examples/perl-language/VERSIONS.md。signatures、class 等特性的开关和警告要在相应选修篇依据 5.38.2 的 feature 文档单独核对;此处既不启用它们,也不屏蔽实验警告。
把样本变成数据契约
examples/perl-language/fixtures/demo.tsv 有三条纯合成记录:API 入队、worker 重试以及一条存在但消息为空串的 INFO。旧入口每行字段按 时间<TAB>等级<TAB>服务<TAB>消息<LF> 排列;parse 返回相同字段,import 返回条数,query 选出指定等级,report 按等级名排序给计数。输入以原始字节读入并显式用 UTF-8 解码,输出再显式编码。累计解析器还由 Time::Local 检查日历日期;它不证明日志来自可信时钟。
图:旧四字段入口的字节与记录边界。
1 | |
在仓库根目录执行 prove -v examples/perl-language/t/00-contract.t:18 个断言通过,退出码 0。import 的 STDOUT 是 IMPORTED<TAB>3<LF>,report 是 TOTAL<TAB>3<LF>INFO<TAB>2<LF>WARN<TAB>1<LF>,两者 STDERR 均空、退出码均 0。反例 import .../fixtures/invalid.tsv 报 line 1: invalid record,STDOUT 空、退出码 2;query .../fixtures/demo.tsv ERROR 的空 STDOUT 则是预期的成功空集,退出码 0,不能用空文件代替执行记录。每条命令和字节金标在 examples/perl-language/evidence/00.md。
Hexo 公开页面不直接保留仓库的 examples/。完整工具、测试、输入金标、RUN.md、VERSIONS.md、Text::CSV 隔离安装模块与发行包、执行证据已一同打入同名素材目录的 实验压缩包(2026-10-06 历史包 SHA-256:927131cc76cb74894970aaab14ac0697e1d2490da2aea192aaecc6287eb9194d)。主线 00–39 和选修 E01–E08 的实验加入后,在全新临时目录重新解包执行 prove -r .../perl-language/t,历史 Linux 解包验收 185 条断言通过;历史快照和校验值见计划。MakeMaker 练习发行包另存于第 37 篇同名素材目录。包的内容与解包命令见同目录 PACKAGE.txt。这只说明本机解包复跑,不等于在未测云主机上通过。
练习:把第三条记录的消息清空与删掉整条记录,两个输入能否等价?不能。前者仍是一条合法日志,import 是 3;后者 import 应为 2,计数也会改变。这里先建立契约,下一篇再看 strict、warnings 与局部变量怎样防止解析器在读入边界依赖全局状态。
原定课程的入口与当前复现环境
2026-10-12 补全后的 完整课程源码包 独立于上面的历史包,SHA-256 为 2b1782bc355f2c85fc0c6162b851095cdb3fe1b601b6c9e44cf74be17bdc2490。包含新旧入口、累计测试、选修源码依赖归档及本次行为证据,不携带本机编译前缀;恢复说明见 课程包复跑说明。Text::CSV_XS、SQLite 等依赖需用目标 5.38.2 解释器重新隔离构建,不能从历史包拷贝 XS 二进制代验。
进入实验前先完成四项自测:变量可以保存值,函数输入与返回值要区分,文件路径不能当成目录,STDOUT 空不能单独判断成功。用已确认的解释器执行 perl -e 'my $x = 0; print defined($x) ? "defined zero\n" : "missing\n"',预期是 defined zero;如果把 defined($x) 换成 $x,零会进入另一分支。零是本课程耗时字段的有效值,这个反例会在 04 和查询参数中继续出现。
从示例目录执行以下小练习,perl_bin 必须换成刚核对的 5.38.2 路径。第一条输入是 ASCII 合成文件;第二条故意不存在,不读取真实业务日志。
1 | |
答案:两个路径检查各输出一行;缺文件报表返回 2,STDOUT 为 0 字节,STDERR 有诊断。course-cli.t 和 replay 保存这些接口的程序断言;以上自测让读者先能解释通道和路径,再进入编码、上下文与引用。status=$? 要紧跟命令,否则它会记录后一个命令的状态。
原定课程需要耗时筛选、逐行拒绝和 JSONL,使用 bin/logtool;旧四字段入口保持其已有实验。新版 fixtures/course.tsv 的五字段依次是 timestamp、level、service、duration_ms、message,四条合法记录加一条坏时间。第四字段空值表示耗时未知,数字零表示已观测的零毫秒。消息允许受约束转义,详见 JSON Lines 专题。
1 | |
复现前先用 command -v perl 和 perl -V 确认实际对象,--version 也打印 $^V。系统 macOS Perl 5.34.1 可执行部分旧实验,但不能代替冻结的 5.38.2 signatures/class 测试。2026-10-12 补全使用同一官方源包在 macOS 本地构建 5.38.2,源码身份不变,构建配置、二进制身份和模块加载路径另存于补全证据;它不是历史 Ubuntu 二进制。构建树解释器与 prove、XS 模块必须属于同一环境,不能拼接系统 prove 与另一版本的核心库。
主入口采用 strict/warnings、按需加载核心模块,没有用版本 bundle 自动打开一组新语法。use utf8 只声明源文件字符;signatures 与实验 class 在相应独立实验中显式启用。Perl 5 与 Raku 的发行版、语法和实现不同,本课程没有执行 Raku,也没有以其结果证明 Perl 5 行为。
一份可复现记录至少包括解释器真实路径、$^V、完整 perl -V、源码摘要、模块及 distribution 版本、feature 开关、命令参数、输入摘要、三个结果通道。版本号相同仍可能配置不同,核心与第三方模块也可能来自不同目录。验证可以先打印 %INC 中加载的路径,再计算文件摘要;只有安装命令退出成功,不能证明本次运行真的用了那个安装目录。
首个失败对照用 perl bin/logtool query --input:缺少值应非零且没有成功数据。成功 import 必须给出 INPUT 5、ACCEPTED 4、REJECTED 1;成功报表给 TOTAL 4。这里用守恒关系约束五字段链路,而不是沿用旧版 IMPORTED 3 来替代新契约。当前累计结果、环境差异和原定 48 项映射以补全矩阵为准;本页上方 185 项记录是历史 Linux 快照。
[PATTERN] 固定运行身份与固定输入契约一起建立基线。只有版本号或只有输出金标,都不足以解释一次跨环境差异。
| 复现对象 | 需要核对 |
|---|---|
| 解释器 | 路径、完整配置、二进制摘要 |
| 语言特性 | 版本与实际 feature 开关 |
| 模块 | distribution、版本与加载路径 |
| 输入输出 | 格式、金标、退出码及两个流 |
参考:Perl 5.38.2 官方发行包 pod/perlintro.pod(Safety net)、pod/perldata.pod(Context);CPAN 发行包及摘要;仓库 examples/perl-language/VERSIONS.md、历史 evidence/00.md 与 writing-plans/perl-language/completion/。






