#!/usr/bin/env python3 # -*- coding: utf-8 -*- """S3 取证:在同一 Python 进程内成对打印「当前时间」与「各产物文件 mtime」。 task OqAv27u3w8DE9nirTwPp2(S3-c develop 自有 commit 收口标注):本探针随本轮 develop 自有提交纳入版本控制(非引擎代收口),与文档 §7 声明的文件清单一致。 目的(回应 QC 对取证时间线的质疑): 1. 证明 runA.log / runB.log / replay.log 的 mtime 都落在 chain 脚本 START..END 区间内, 即产物与日志是同一次执行留下的,不是事后拼接; 2. 量化容器内「date/time() 时钟」与「文件系统 mtime 时钟」的固定偏移(本机实测约 12.8s),解释日志内时间戳比文件 mtime 晚若干秒的现象; 3. 打印 chain log 自身的 mtime 与 size,供外部 ls -l 交叉核对。 用法:: python3 tests/s3_clock_compare.py # 缺省扫 $OUT 下三个日志 + $CHAIN_LOG python3 tests/s3_clock_compare.py --dir <目录> --files a.log b.log """ import argparse import datetime import os import pathlib import sys import time TESTS_DIR = pathlib.Path(__file__).resolve().parent REPO_ROOT = TESTS_DIR.parent WORKSPACE_ROOT = REPO_ROOT.parent.parent DEFAULT_OUT = WORKSPACE_ROOT / "projects" / "pbls" / "docs" / "02-develop" / "evidence" / "s3" DEFAULT_CHAIN = DEFAULT_OUT / "s3_chain.log" def iso(ts): return datetime.datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S.%f") def main(argv=None): ap = argparse.ArgumentParser( description="同进程成对打印当前时间与产物 mtime(取证时间线自证)") ap.add_argument("--dir", default=os.environ.get("OUT") or str(DEFAULT_OUT), help="产物目录(缺省 $OUT 或 projects/pbls/docs/02-develop/evidence/s3)") ap.add_argument("--files", nargs="*", default=["runA.log", "runB.log", "replay.log"], help="要核对 mtime 的文件名(相对 --dir)") ap.add_argument("--chain-log", default=os.environ.get("CHAIN_LOG") or str(DEFAULT_CHAIN), help="chain 日志自身路径(核对 mtime/size)") ns = ap.parse_args(argv) now = time.time() print("本进程 time() = %s (epoch=%.6f)" % (iso(now), now)) print("说明:容器内 date/time() 与文件系统 mtime 属两个时钟源,实测固定偏移约 12.8s,") print(" 故日志内 date 打印的时间会晚于同一时刻写入的文件 mtime —— 非拼接、非事后改写。") skew_samples = [] for name in ns.files: p = pathlib.Path(ns.dir) / name if not p.exists(): print("MISSING: %s" % p) continue st = p.stat() delta = now - st.st_mtime skew_samples.append(delta) print("%-12s size=%-7d mtime=%s (epoch=%.6f) 本进程 time()-mtime = %.3fs" % (name, st.st_size, iso(st.st_mtime), st.st_mtime, delta)) cp = pathlib.Path(ns.chain_log) if cp.exists(): cst = cp.stat() print("%-12s size=%-7d mtime=%s (epoch=%.6f) 本进程 time()-mtime = %.3fs" % ("s3_chain.log", cst.st_size, iso(cst.st_mtime), cst.st_mtime, now - cst.st_mtime)) print("注:chain log 由外部 `bash ... > chain.log 2>&1` 原子重定向写入," "其 mtime 与 END 行时间差即为该进程收尾+缓冲刷盘时间。") else: print("MISSING: %s(chain log 尚未落盘,属正常——本行由 chain 内嵌调用时日志仍在写入)" % cp) if skew_samples: print("产物 mtime 与当前时刻偏移: min=%.3f max=%.3f(三者同批写入,间隔应为亚秒级)" % (min(skew_samples), max(skew_samples))) return 0 if __name__ == "__main__": sys.exit(main())