multilog(8)
π multilog(8) β the manual but make it a group chat π
hiii bestie π«Ά welcome to multilog, section 8 of the System Manager's Manual. pull up a chair, grab a strawberry π, we're gonna get you logging like a main character.
β¨ NAME β¨
multilog β reads a sequence of lines from stdin and appends selected lines to any number of logs. that's it, that's the whole job, and she does it flawlessly π
β¨ SYNOPSIS β¨
multilog script
β¨ DESCRIPTION β¨
okay so script is literally just any number of arguments. every argument = one action β¨ and the actions are carried out in order, once per line of input. no skipping, no reordering, just vibes in sequence.
not me forgetting this: actions may contain shell metacharacters, so you have to quote them when you run multilog from a shell. quote your patterns bestie, protect your peace π
the whole lifecycle, laid out:
multilogexits0when it sees the end of stdin. if stdin has a partial final line,multiloginserts a final newline. tidy. iconic.multilogwrites a message to stderr and exits111, without reading any input, if it runs out of memory, or if anothermultilogprocess is writing to one of the same automatically rotated logs. π so don't do that.- if
multiloghas trouble writing to disk after it starts reading input, it writes a message to stderr, pauses, and tries again, without losing any data. but lowkey be aware: this may block any program feeding input tomultilog. - if
multilogreceives aTERMsignal, it will read and process data until the next newline, and then exit, leaving stdin at the first byte of data it has not processed. graceful exit queen π
πΈ SELECTING LINES πΈ
every line is initially selected. from there, your actions decide who stays and who goes.
-patternβ deselects the line if pattern matches the line.+patternβ selects the line if pattern matches the line.
pattern is a string of stars and non-stars. it matches any concatenation of strings matched by all the stars and non-stars in the same order. a non-star matches itself. a star before the end of pattern matches any string that does not include the next character in pattern. a star at the end of pattern matches any string. yes bestie, it's giving wildcard energy π¦
for example, the action
+hello
selects hello. it does not select hello world. picky? no, correct.
the action
-named[*]: Cleaned cache *
deselects named[135]: Cleaned cache of 3121 RRs. the first star matches any string that does not include a right bracket. see how that works? chef's kiss π
the action
-*
deselects every line. bye to everyone, no survivors, periodt.
to save memory, multilog actually checks pattern against only the first 1000 characters of each line. yep, only the first 1000. the rest is just there for the aesthetic.
π ALERTS π
the action
eβ prints (the first 200 bytes of) each selected line to stderr.
that's it. that's the whole action. she's short, she's loud, she ate π
π STATUS FILES π
the action
=fileβ replaces the contents of file with (the first 1000 bytes of) each selected line, padded with newlines to 1001 bytes. there is no protection of file against power outages. β οΈ like, none. so keep that in mind.
for example, the sequence of actions
-*
+STAT*
=log/status
maintains log/status as a copy of the most recent line starting with STAT. one file, always fresh, always the latest STAT. obsessed β¨
β TIMESTAMPING β
the action
tβ inserts an@, a precise timestamp, and a space in front of each line, using the same format astai64n(8). this is required to be the first action. like, required required. don't fight it π
patterns apply to the line after the timestamp is inserted. so for example, if
multilog t '-*' '+* fatal: *' ./main
reads the line
fatal: out of memory
then it will log a line such as
@400000003b4a39c23294b13c fatal: out of memory
with the first * matching the timestamp. iykyk π
you can use tai64nlocal(8) to convert these timestamps to human-readable form. your future self will thank you.
π AUTOMATICALLY ROTATED LOGS π
if dir starts with a dot or slash then the action
dirβ appends each selected line to a log named dir. if dir does not exist,multilogcreates it. making directories out of thin air, main character energy.
π¨ do not attempt to write to one log from two simultaneous multilog processes, or two actions in one process. just don't. this is the one rule fr fr.
the log format is as follows: dir is a directory containing some number of old log files, a log file named current, and other files for multilog to keep track of its actions. each old log file has a name beginning with @, continuing with a precise timestamp showing when the file was finished, and ending with one of the following codes:
.sβ this file is completely processed and safely written to disk. slay, done, finished π.uβ this file was being created at the moment of an outage. it may have been truncated and has not been processed. π
beware that NFS, async filesystems, and softupdates filesystems may discard files that were not safely written to disk before an outage. so like... know your filesystem bestie.
while multilog is running, current has mode 644. if multilog sees the end of stdin, it writes current safely to disk, and sets the mode of current to 744. when it restarts, it sets the mode of current back to 644 and continues writing new lines. the cycle continues, iconic behavior.
when multilog decides that current is big enough, it writes current safely to disk, sets the mode of current to 744, and renames current as an old log file. the action
ssizeβ sets the maximum file size for subsequentdiractions.multilogwill decide thatcurrentis big enough ifcurrenthas size bytes. (multilogwill also decide thatcurrentis big enough if it sees a newline within 2000 bytes of the maximum file size; it tries to finish log files at line boundaries. thoughtful π₯Ή) size must be between4096and16777215. the default maximum file size is99999.
in versions 0.75 and above: ifmultilogreceives anALRMsignal, it immediately decides thatcurrentis big enough, ifcurrentis nonempty. π noted.
the action
nnumβ sets the number of log files for subsequentdiractions. after renamingcurrent, ifmultilogsees num or more old log files, it removes the old log file with the smallest timestamp. num must be at least2. the default number of log files is10.
the action
!processorβ sets a processor for subsequentdiractions.multilogwill feedcurrentthrough processor and save the output as an old log file instead ofcurrent.multilogwill also save any output that processor writes to descriptor5, and make that output readable on descriptor4when it runs processor on the next log file. for reliability, processor must exit nonzero if it has any trouble creating its output;multilogwill then run it again. note that running processor may block any program feeding input tomultilog. π¬ so, you know, keep an eye on it.
π¦ SEE ALSO π¦
supervise(8), svc(8), svok(8), svstat(8), svscanboot(8), svscan(8), readproctitle(8), fghack(8), pgrphack(8), tai64n(8), tai64nlocal(8), setuidgid(8), envuidgid(8), envdir(8), softlimit(8), setlock(8)
http://cr.yp.to/daemontools.html
okay that's the whole page bestie π«Ά the manual header says multilog(8) with System Manager's Manual up top, and the footer is just multilog(8) again β she's from the daemontools crew over at http://cr.yp.to/daemontools.html β¨ go read the friends, they're all linked above. ily, happy logging, don't run two writers on one log πππΈ
π¦ where this page comes from
- debian bookworm: daemontools 1:0.76-8.1 Β· LicenseRef-public-domain
- debian trixie: daemontools 1:0.76-14 Β· LicenseRef-public-domain
- nixpkgs unstable: daemontools 0.76
- ubuntu jammy: daemontools 1:0.76-7
- ubuntu noble: daemontools 1:0.76-10 Β· LicenseRef-public-domain
- ubuntu questing: daemontools 1:0.76-15
- ubuntu resolute: daemontools 1:0.76-15build1 Β· LicenseRef-public-domain
- ubuntu stonking: daemontools 1:0.76-15build1 Β· LicenseRef-public-domain
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms