stenotype(1)
π stenotype(1) β the manual page, but make it make sense π
okay bestie, sit down, hydrate, because today we're talking about stenotype from the stenographer fam (she's on version 1.0.1, icon behaviour) and honestly? she's that girl. no cap.
β¨ NAME β¨
stenotype β dump raw packets to disk. that's it. that's the whole job. she dumps packets, she goes home, she doesn't text back. π
πΈ SYNOPSIS πΈ
stenotype [-qv?] [--aiops=NUM] [--blocks=NUM] [--count=NUM]
[--dir=STRING] [--fanout_id=NUM] [--fanout_type=NUM]
[--fileage_sec=NUM] [--filesize_mb=NUM] [--filter=STRING]
[--gid=NUM] [--iface=STRING] [--index_nicelevel=NUM] [--no_index]
[--no_watchdogs] [--preallocate_file_mb=NUM] [--seccomp=STRING]
[--threads=NUM] [--uid=NUM] [--help] [--usage]
like yeah she's got a lot of flags, she's high maintenance in the most productive way possible π«Ά
π¦ DESCRIPTION π¦
so stenotype is a whole mechanism for dumping raw packets to disk fast as hell. her whole philosophy? keep the interface simple β and like, no file rotation, because that's literally left as an exercise for the reader π (yes fr, go build it yourself bestie, you got this).
but simple interface β weak tool. she's very powerful. like, scary powerful. main character energy.
stenotype runs a NIC β disk pipeline that's specifically engineered to push output to disk as fast as physically possible while only ever using the kernel's own built-in mechanisms. no extra middlemen, no drama, no copy-paste layers. periodt.
- NIC β RAM:
stenotypeusesMMAP'dAF_PACKETwith1MBblocks and a high timeout, so it can offload the actual writing of packets β and deciding how they're laid out β to the kernel. the kernel stuffs every packet it can into1MB, then taps the userspace process on the shoulder like "hey, there's a block available in theMMAP'd ring buffer β¨". and the best part? it guarantees no overruns (meaning no packet is ever split across the1MBboundary, thank u) plus nice alignment to memory pages. we love a considerate kernel. - RAM β Disk: since the kernel already handed us one single
1MBblock of packets that's all nicely aligned, we can justO_DIRECTwrite it straight to disk. no extra copying, no kernel buffering, no nonsense. and to keep sequential reads going strong, all disk IO happens asynchronously viaio_submit(which, btw, works specifically forO_DIRECTfiles... joy! π). and because the write is async, we use that waiting-around time to do our own in-memory processing and indexing. multitasking queen π
there are N async IO operations available, and N is flag-specified (--aiops, we'll get there). once we've used up all N of them, we block until one that's already in use finishes, then reuse it. recycling!! sustainable!! π
the whole pipeline, step by step, for my visual learners:
- kernel gives userspace a
1MBblock of packets - userspace iterates over packets in block, updates any indexes
- userspace starts async IO operation to write block to disk
- after N async IO operations are submitted, we synchronously wait for the least recent one to finish.
- when an async IO operation finishes, we release the
1MBblock back to the kernel to write more packets.
it's giving assembly line but make it packets. obsessed.
π OPTIONS π
--aiops=NUMβ max number of async IO operations. (this is the N from the pipeline lore π«Ά)--blocks=NUMβ total number of blocks to use, and remember: each one is1MB.--count=NUMβ total number of packets to read. set it to-1to read forever and ever and ever (she's committed).--dir=STRINGβ directory to store packet files in. tell her where to drop the goods.--fanout_id=NUMβ if you're fanning out across processes, set this.--fanout_type=NUMβTPACKET_V3fanout type to fanout packets.--fileage_sec=NUMβ files older than this many secs get rotated.--filesize_mb=NUMβ max file size in MB before the file gets rotated.--filter=STRINGβ a BPF compiled filter used to pick which packets get captured. important: this has to be a compiled BPF in hexadecimal, which you can get from a human readable filter expression using the providedcompile_bpf.shscript. (yes, hex. she doesn't do vibes-based filtering, sorry bestie π)--gid=NUMβ drop privileges to this group.--iface=STRINGβ interface to read packets from. name the NIC, girl.--index_nicelevel=NUMβ nice level of indexing threads.--no_indexβ do not compute or write indexes. (skipping the index arc entirely π)--no_watchdogsβ don't start any watchdogs.--preallocate_file_mb=NUMβ when creating new files, preallocate to this many MB.-qβ quiet logging. each-qcounteracts one-v, it's a whole tug of war πͺ’--seccomp=STRINGβ seccomp style, one of'none','trace','kill'. pick your fighter.--threads=NUMβ number of parallel threads to read packets with.--uid=NUMβ drop privileges to this user.-vβ verbose logging, and you can give it multiple times. more v's, more yapping π£οΈ-?,--helpβ give this help list.--usageβ give a short usage message.
heads up bestie:-qand-vliterally cancel each other out. one-vvs one-qis a fair fight. plan accordingly. βοΈ
okay and that's the whole page!! no boring parts skipped, every flag accounted for, she ate and left no crumbs π₯
this was stenographer version 1.0.1, dated 29 January 2026 β so like, recent. fresh. relevant. bye bestie, go dump some packets, you're gonna slay π
β¨
π¦ where this page comes from
- ubuntu resolute: stenographer 1.0.1-7build1
- ubuntu stonking: stenographer 1.0.1-7build1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms