Oninit® Logwalker — Operations
Logwalker is a single command-line binary. There is no daemon, no configuration file, no state directory; every invocation is one walk of one log uniqid with the flags you pass on the command line. This page documents the flags and the runtime contract; the Output Schema page documents what each line of the resulting text stream means.
Synopsis
logwalker -n <uniqid> [options] # walk one log logwalker -t <db:table|partnum> --from-time <dt> [options] # track one object over a date window logwalker -t <db:table|partnum> --from-log <id> [options] # track one object over a log range
Command-line flags
| Flag | Meaning |
|---|---|
| -n <uniqid> | Required for a single-log walk (omitted in -t track mode, which derives its log set from the range). The logical-log uniqid to walk. Must be an integer the engine still has on disk — archived logs that have been recycled past the LOGFILES ring are not walkable. Query syslogs or onstat -l to see what's currently available. |
| -m <count> | Cap the number of records printed (0 = unlimited). Useful for sanity-checking the output of a big log without waiting for the full walk. Default 0. |
| -f, --filter T,U,… | Comma-separated list of record types to print. Type names (BEGIN, HINSERT, COMMIT, …) or numeric hex codes (0x0028,0x0002) accepted. Records of other types are silently skipped. |
| -t, --table <tgt> | Object-track mode: print every record whose primary partition matches <tgt> across a range of logs, rather than walking one log in full. <tgt> is either <database>:<table> (resolved to a data partnum through the phase-1 catalog) or a partnum given in hex (0x…) or decimal. Requires a start of range (--from-log or --from-time); pairs with an end (--to-log / --to-time). Composes with -f, --decode-rows and every output mode. Under --chunk (engine offline) the catalog is unreachable, so <tgt> must be a numeric partnum — a db:table name is refused. Replaces -n: a track walk derives its own log set from the range, so you don't pass a single uniqid. In HUMAN and --group-by-xid output it also reports each matched transaction's boundary, so you can tell whether a change actually persisted — see Transaction boundaries below. See the object-track example. |
| --from-log <id> | Start uniqid for a -t range walk. Must still be on disk — if it is older than MIN(uniqid) in syslogs the walk is refused with the oldest walkable uniqid named (overwritten logs can't be walked). |
| --to-log <id> | End uniqid for the range (inclusive). Optional — defaults to the last log on disk (MAX(uniqid)). |
| --from-time <dt> | Start the range at the log covering a datetime instead of a uniqid — the date-scoped form of --from-log. <dt> is 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DD' (time assumed 00:00:00). logwalker probes each log's first BEGIN/COMMIT timestamp and binary-searches for the log that contained <dt>. Mutually exclusive with --from-log. |
| --to-time <dt> | End the range at the log covering a datetime (same format as --from-time). Mutually exclusive with --to-log. |
| --decrypt | Decrypt encrypted-dbspace (EAR) logical logs before walking. A plain walk of an encrypted log only yields ciphertext, so logwalker refuses it with a pointer to this flag. Requires --keystore; --dbsnum is auto-detected. The crypto reader is statically linked in — no extra package. Needs gsk8capicmd_64 (GSKit) on PATH. |
| --keystore <ks> | Keystore base for --decrypt. A bare name (no /) resolves under $INFORMIXDIR/etc/ — the Informix default keystore location — so you can pass the keystore name straight from onconfig DISK_ENCRYPTION. A value containing / is used as a full path verbatim. The raw DISK_ENCRYPTION value is accepted too: a leading keystore= and a trailing ,cipher=… are stripped. Do not add the .p12/.sth suffix — the library appends them. |
| --dbsnum <N> | The DBSPACE number — NOT the chunk number. Used for --decrypt key derivation. Best practice: omit it — logwalker auto-detects the dbspace from the log's chunk via the resolve. Pass it only to override. The common mistake is giving the chunk number (from onstat -l) instead of the dbspace number (from onstat -d / sysdbspaces): a wrong value silently derives the wrong key and the output stays ciphertext (logwalker flags this with a [CRITICAL] "no valid records" notice). See Troubleshooting. |
| -r, --decode-rows | Schema-aware row decoding. On startup, after the cheap systabnames phase, logwalker walks every distinct accessible database and pulls syscolumns into a per-table column list. HINSERT / HUPAFT / HUPBEF / HDELETE bodies then render as (col1=val1, col2=val2, …) instead of a hex dump. Adds startup latency proportional to the number of databases on the instance. |
| --compat <fmt> | Alternate output format. The only supported value is onlog, which emits the legacy onlog -l 6-column shape (addr len type xid id link) plus per-type tail extras for downstream tooling that already parses that form. See the --compat onlog example. |
| --group-by-xid | Wrap each transaction's records with --- TX <xid> BEGIN @ LSN U:<low> --- / --- TX <xid> COMMITTED @ LSN U:<low> --- framing markers. Because xid is reused after a transaction completes, later BEGINs with the same numeric xid as a prior frame get an (xid REUSED) tag so the framing stays unambiguous. |
| -u <user>, -p <pass> | Source-DB user and password for the sysmaster connect. Optional — if the running OS user already has CONNECT privilege on sysmaster (e.g. informix) the catalog load works without explicit credentials. |
| -s <server> | Override INFORMIXSERVER for the sysmaster connection. Defaults to the environment variable. |
| -V | Print version and exit. |
| -h, --help | Print usage and exit. |
Transaction boundaries in track mode
A track walk filters to the records that carry the tracked partition, so on its own it shows that a row changed — an HINSERT, an HDELETE — but not whether the change persisted. An INSERT whose transaction never reached a COMMIT (or that ended in a ROLLBACK) was undone; the bare record can't tell you which. Because BEGIN / COMMIT / ROLLBACK records carry no partition number, the plain filter would drop exactly the context you need.
So in HUMAN and --group-by-xid output, track mode passes through the boundary of every transaction that touches the object. The first time one of a transaction's records matches, logwalker prints an opening marker carrying the BEGIN's pid, uid and start time; when that transaction commits or rolls back, it prints a verdict:
=== TX 4812 opened on coris.sysprocedures (pid=73628 uid=1000 began 06/16/2026 14:02:11) === LSN 480661:0x00000080 xid=4812 INSERT into coris.sysprocedures (rowid 0x00000101, 64 bytes) === TX 4812 COMMITTED @ 06/16/2026 14:02:11 — 1 tracked change(s) PERSISTED === === TX 4815 opened on coris.sysprocedures (pid=73630 uid=1000 began 06/16/2026 14:02:14) === LSN 480661:0x000001dc xid=4815 DELETE from coris.sysprocedures (rowid 0x00000090) === TX 4815 ROLLED BACK — 1 tracked change(s) DISCARDED (did NOT persist) ===
At the end of the walk a one-line summary tallies the transactions seen (committed, rolled back, open). Any transaction still open — one that touched the tracked object but whose COMMIT or ROLLBACK lies beyond the walked range — is flagged explicitly, because its persistence is genuinely unknown until you walk far enough to see its fate:
# ---------------------------------------------------------- # transaction summary: 1 committed, 1 rolled back, 1 open # WARNING: 1 tracked transaction(s) had NO COMMIT/ROLLBACK in # the walked range — persistence UNKNOWN. Extend --to-log to # see their fate: # TX 4820 2 change(s) (pid=73641 began 06/16/2026 14:02:20)
The fix for an open transaction is simply to widen the range (raise --to-log, or drop it so the walk runs to the last log on disk). If the BEGIN itself fell before the start of the range, the opening marker says (BEGIN before walked range) rather than inventing a timestamp. The --compat onlog format is left untouched — it stays a pure six-column stream for scripts that parse it.
Pre-flight gates
Before the walk begins, logwalker enforces three gates and refuses to start with a [CRITICAL] diagnostic if any fail:
- sysmaster connect — if the ESQL/C CONNECT to sysmaster fails, the deployment-constraint reminder is printed and the binary exits non-zero. This catches the common "wrong INFORMIXSERVER" / "wrong INFORMIXSQLHOSTS" mistake.
- uniqid resolve — the requested uniqid must exist in the current syslogs view. Archived-and-recycled uniqids and never-existed uniqids both fail here.
- chunk R_OK — every chunk path in the resolved extent map for the uniqid must be readable by the OS user running logwalker. If any one chunk fails access(R_OK), the binary refuses with the deployment-constraint reminder. No partial walks; either the operator can read every chunk in the extent map or the walk doesn't start.
Catalog phases
Two catalog-load phases run at startup, sequenced to amortize their cost differently:
- Phase 1 (names only) — walks sysmaster.systabnames in one read. Builds a partnum → (dbname, owner, tabname) lookup covering every named partition on the instance (tables and indexes both; systabnames is the unified pseudo-view). Single connection, ~2–3 seconds on a 2K-partition instance. Auto-loaded for HUMAN and GROUPED modes so partnums render as their <db>.<table> names; skipped for --compat onlog (whose output has no name slot).
- Phase 2 (column maps) — gated on --decode-rows. For each unique dbname collected in phase 1, opens a separate ESQL connection and pulls syscolumns ORDER BY colno into the table's column list. Cost is proportional to the number of databases, not the number of tables; closes each connection before the walker starts emitting records. Databases the running user can't CONNECT to are logged as warnings (SQLCODE -387 / -329 / -23197) and their tables' rows render as hex rather than decoded values.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Walk completed; records emitted to stdout. |
| 1 | Pre-flight gate failed (sysmaster connect, uniqid resolve, or chunk R_OK), or unrecoverable I/O error mid-walk. |
| 2 | Usage error (missing -n, bad flag combination, unknown --compat value). |