68 lines
2.0 KiB
Bash
68 lines
2.0 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# retention-verify-archive.sh — retention piece 1 (board bug b67084660385).
|
||
|
|
# Verifies one archive file: checksum, integrity, clean listing, spot-extract.
|
||
|
|
# Usage: retention-verify-archive.sh <path-to-.jsonl.gz-or-.jsonl>
|
||
|
|
# Exits non-zero on any verification failure. Missing file = SKIP (rc 0).
|
||
|
|
set -uo pipefail
|
||
|
|
|
||
|
|
fail() { echo "FAIL verify $1: $2"; exit 1; }
|
||
|
|
|
||
|
|
P="${1:?usage: $0 <archive-path>}"
|
||
|
|
|
||
|
|
if [ ! -f "$P" ]; then
|
||
|
|
echo "SKIP verify: $P does not exist"
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "== verify $P =="
|
||
|
|
|
||
|
|
# 1. checksum sidecar
|
||
|
|
if [ -f "$P.sha256" ]; then
|
||
|
|
( cd "$(dirname "$P")" && sha256sum -c "$(basename "$P").sha256" ) \
|
||
|
|
|| fail "$P" "sha256 mismatch"
|
||
|
|
echo " checksum: OK"
|
||
|
|
else
|
||
|
|
echo " checksum: no sidecar (archiver writes one for new .gz files)"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# 2. integrity + clean listing for gzip archives
|
||
|
|
if [[ "$P" == *.gz ]]; then
|
||
|
|
gzip -t "$P" || fail "$P" "gzip integrity test failed"
|
||
|
|
echo " integrity: gzip -t OK"
|
||
|
|
echo " listing:"; gzip -l "$P" | sed 's/^/ /'
|
||
|
|
reader="zcat"
|
||
|
|
else
|
||
|
|
reader="cat"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# 3. spot-extract: first 3 and last 3 lines must be valid JSON
|
||
|
|
n=0
|
||
|
|
while IFS= read -r line; do
|
||
|
|
n=$((n+1))
|
||
|
|
echo "$line" | python3 -c 'import json,sys; json.loads(sys.stdin.read())' \
|
||
|
|
|| fail "$P" "line $n is not valid JSON"
|
||
|
|
done < <( { $reader "$P" | head -3; $reader "$P" | tail -3; } 2>/dev/null )
|
||
|
|
|
||
|
|
total="$( $reader "$P" | wc -l )"
|
||
|
|
echo " spot-extract: first/last 3 lines valid JSON ($total total lines)"
|
||
|
|
|
||
|
|
# 4. spot-extract timestamps: report newest/oldest ts seen in the sample
|
||
|
|
sample="$($reader "$P" | head -2000)"
|
||
|
|
ts_line="$(echo "$sample" | python3 -c '
|
||
|
|
import json,sys
|
||
|
|
keys=("ts","timestamp","time","created_at","sent_at","resolved_at")
|
||
|
|
seen=[]
|
||
|
|
for line in sys.stdin:
|
||
|
|
line=line.strip()
|
||
|
|
if not line: continue
|
||
|
|
try: rec=json.loads(line)
|
||
|
|
except Exception: continue
|
||
|
|
for k in keys:
|
||
|
|
if rec.get(k): seen.append(str(rec[k])); break
|
||
|
|
seen=sorted(set(seen))
|
||
|
|
print(("oldest="+seen[0]+" newest="+seen[-1]) if seen else "no-ts-field")
|
||
|
|
')"
|
||
|
|
echo " timestamps: $ts_line"
|
||
|
|
|
||
|
|
echo "OK verify $P"
|