s6

Mirror/fork of https://skarnet.org/software/s6/
git clone https://ccx.te2000.cz/git/s6
Log | Files | Refs | README | LICENSE

s6-log.html (26387B)


      1 <html>
      2   <head>
      3     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      4     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      5     <meta http-equiv="Content-Language" content="en" />
      6     <title>s6: the s6-log program</title>
      7     <meta name="Description" content="s6: the s6-log program" />
      8     <meta name="Keywords" content="s6 command s6-log log logger logging multilog" />
      9     <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
     10   </head>
     11 <body>
     12 
     13 <p>
     14 <a href="index.html">s6</a><br />
     15 <a href="//skarnet.org/software/">Software</a><br />
     16 <a href="//skarnet.org/">skarnet.org</a>
     17 </p>
     18 
     19 <h1> The s6-log program </h1>
     20 
     21 <p>
     22 s6-log is a reliable logging program with automated log rotation, similar to
     23 daemontools' <a href="https://cr.yp.to/daemontools/multilog.html">multilog</a>,
     24 with full POSIX regular expression support.
     25 </p>
     26 
     27 <h2> Interface </h2>
     28 
     29 <pre>
     30      s6-log [ -d <em>notif</em> ] [ -q | -v ] [ -b ] [ -p ] [ -l <em>linelimit</em> ] [ -t <em>lastlinetimeout</em> ] [ -- ] <em>logging script</em>
     31 </pre>
     32 
     33 <p>
     34 s6-log reads and compiles <em>logging script</em> to an internal
     35 form. Then it reads its standard input, line by line, and performs actions
     36 on it, following the script it is given. It does its best to ensure there
     37 is <em>never any log loss</em>. It exits cleanly when stdin closes or when
     38 it receives a SIGTERM or a SIGHUP.
     39 </p>
     40 
     41 <h2> Options </h2>
     42 
     43 <ul>
     44  <li> <tt>-d&nbsp;<em>notif</em></tt>&nbsp;:
     45 <a href="notifywhenup.html">readiness notification.</a>
     46 With this option, s6-log writes a newline character to file descriptor
     47 <em>notif</em> when it is <em>ready</em>, i.e. when it has successfully
     48 parsed its logging script and initialized all its necessary resources
     49 such as the logdirs defined in the script, and is now listening to stdin
     50 in order to process log lines. </li>
     51  <li> <tt>-b</tt>&nbsp;: blocking mode. With this option, s6-log stops
     52 reading its standard input while it has unflushed buffers. This ensures that
     53 every log line has been fully processed before reading the next one; this is also
     54 <a href="https://cr.yp.to/daemontools/multilog.html">multilog</a>'s behaviour.
     55 By default, s6-log keeps reading from stdin even if its buffers still
     56 contain data. <tt>-b</tt> is safer, but may slow down your service; the default
     57 is faster, but may lead to unbound memory use if you have a lot of output to
     58 write to a slow file system. </li>
     59  <li> <tt>-p</tt>&nbsp;: protect against SIGTERM. Do not exit on receipt of a
     60 SIGTERM; only exit on a SIGHUP or when reading EOF on stdin. This is useful
     61 for a logger that you really do not want to lose even if automated
     62 administration (e.g. the downing of a supervision tree) would kill it. </li>
     63  <li> <tt>-q | -v</tt>&nbsp;: quiet | verbose. Decreases | increases s6-log's
     64 verbosity, i.e. which messages are sent to stderr. The default verbosity is 1.
     65 Currently supported verbosity levels:
     66   <ul>
     67    <li> 0: only write alerts and fatal errors </li>
     68    <li> 1: write alerts, warnings and fatal errors </li>
     69   </ul> </li>
     70  <li> <tt>-l&nbsp;<em>linelimit</em></tt>&nbsp;: if a log line is longer than
     71 <em>linelimit</em> bytes, split it by inserting a newline after the
     72 <em>linelimit</em>th byte. After the split, the remainder of the line will
     73 also be processed, so it will go through the selection process, timestamping,
     74 etc. <em>linelimit</em> cannot be less than 48, unless it is 0 (which means
     75 infinite). The default is 8192 bytes. Setting <em>linelimit</em> to 0 ensures
     76 that lines will never be split; this may cause important memory consumption
     77 by s6-log if it is fed extremely long lines, so use with caution. </li>
     78  <li> <tt>-t&nbsp;<em>lastlinetimeout</em></tt>&nbsp;: if s6-log receives
     79 a termination signal but has a read a partial line in its buffer, it will
     80 wait for at most <em>lastlinetimeout</em> milliseconds for its service
     81 to send it the remainder of the line; if it still hasn't read a newline
     82 character by then, it will add a newline character itself and process the
     83 line, then exit. By default, <em>lastlinetimeout</em> is 2000, which means
     84 s6-log will wait for at most 2 seconds for completion of its last partial line.
     85 If <em>lastlinetimeout</em> is given as <strong>0</strong>, then s6-log
     86 will wait forever; it won't exit until it actually reads a newline or EOF. </li>
     87 </ul>
     88 
     89 <h2> Logdirs </h2>
     90 
     91 <p>
     92 A <em>logdir</em> (<em>logging directory</em>) is a place where logs are
     93 stored. s6-log can be scripted to write into one or more logdirs.
     94 </p>
     95 
     96 <p>
     97  A logdir may contain the following files:
     98 </p>
     99 
    100 <ul>
    101  <li> <tt>lock</tt>: this file is locked by s6-log at start,
    102 to make sure only one instance is running at the same time. </li>
    103  <li> <tt>current</tt>: the file where selected log lines are appended.
    104 If <tt>current</tt> has the executable-by-user flag, it means that no
    105 s6-log process is currently writing to it and the previous
    106 s6-log process managed to cleanly finalize it. If it does not,
    107 either an s6-log process is writing to it or the previous one
    108 has been interrupted without finalizing it. </li>
    109  <li> <tt>state</tt>: last processor's output, see below. </li>
    110  <li> <tt>previous</tt>: a rotation is happening in that logdir. </li>
    111  <li> <tt>processed</tt>, <tt>newstate</tt>: a rotation is happening
    112 in that logdir and the processor script is running. </li>
    113  <li> timestamped files: those files are @<em>timestamp</em>.s or
    114 @<em>timestamp</em>.u and are old log files that have been processed
    115 and rotated (if they're ending in .s) or that were the <tt>current</tt>
    116 file when s6-log got interrupted (if they're ending in .u), in which
    117 case they have not been processed. </li>
    118 </ul>
    119 
    120 <h3> Rotation </h3>
    121 
    122 <p>
    123  In a logdir, selected lines are appended to the <tt>current</tt> file.
    124 When <tt>current</tt> becomes too big, a <em>rotation</em> happens.
    125 The <tt>current</tt> file will be possibly <em>processed</em>, then
    126 it will become an <em>archived</em> log file named
    127 @<em>timestamp</em>.s, where <em>timestamp</em>, a
    128 <a href="//skarnet.org/software/skalibs/libstddjb/tai.html">TAI64N</a>
    129 timestamp, is the absolute time of the rotation. If there are too
    130 many archived log files in the logdir, the older ones are then
    131 deleted. Logging then resumes, to a brand new <tt>current</tt>
    132 file.
    133 </p>
    134 
    135 <p>
    136  You can use this mechanism to ensure that your logs never fill up
    137 the available disk space, for instance: something that neither
    138 syslogd, nor syslog-ng, nor rsyslog offers.
    139 </p>
    140 
    141 <h3> Processors </h3>
    142 
    143 <p>
    144  A <em>processor</em> script can be set for every logdir. When a rotation
    145 occurs, <tt>current</tt> (which has then been renamed <tt>previous</tt>) is
    146 fed to <em>processor</em>'s stdin, and <em>processor</em>'s stdout is saved
    147 and archived. <em>processor</em> can also read the <tt>state</tt> file
    148 on its fd 4; what it writes to its fd 5 will be saved as the next
    149 <tt>state</tt> file, for the next rotation. A processor script runs with
    150 the logdir as its working directory.
    151 </p>
    152 
    153 <p>
    154  Processors should not background themselves: s6-log considers the
    155 processing done when its <em>processor</em> direct child dies.
    156 Processors should exit 0 on success and nonzero on failure; if a
    157 processor fails, s6-log will try it again after some
    158 <em>cooldown</em> time.
    159 </p>
    160 
    161 <p>
    162  Processors make s6-log Turing-complete by allowing you to use any
    163 external program to handle log files that are going to be archived.
    164 </p>
    165 
    166 <h2> Logging script syntax </h2>
    167 
    168 <p>
    169  When starting up, s6-log reads its arguments one by one; this
    170 argument sequence, or <em>directive sequence</em>, forms a
    171 <em>logging script</em> which tells s6-log what to log, where, and how.
    172 </p>
    173 
    174 <p>
    175  Every directive can be a <em>selection</em> directive, a <em>control</em>
    176 directive or an <em>action</em> directive. A valid logging script always
    177 contains at least one action directive; every action directive can be
    178 preceded by zero or more selection or control directives. s6-log will exit 100
    179 if the script is invalid. If it can process the script but the last directive
    180 is not an action directive, s6-log will emit a warning.
    181 </p>
    182 
    183 <h3> Selection directives </h3>
    184 
    185 <p>
    186  These directives tell s6-log whether to select or deselect lines it reads
    187 from stdin; actions will only happen on selected lines. By default, every
    188 line is selected.
    189 </p>
    190 
    191 <ul>
    192  <li> <strong>+<em>regexp</em></strong>: select yet-unselected lines that match <em>regexp</em>, which must be a
    193 <a href="https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04">POSIX
    194 Extended Regular Expression</a>. </li>
    195  <li> <strong>-<em>regexp</em></strong>: deselect yet-selected lines that match <em>regexp</em>, which must be a
    196 POSIX Extended Regular Expression. </li>
    197  <li> <strong>f</strong>: select exactly lines that have not yet been acted
    198 upon (i.e. that were always deselected when the script encountered an action
    199 directive). </li>
    200 </ul>
    201 
    202 <h3> Control directives </h3>
    203 
    204 <p>
    205  These directives tune s6-log's behaviour for the next actions.
    206 </p>
    207 
    208 <ul>
    209  <li> <strong>n<em>number</em></strong>: next logdirs will contain up to
    210 <em>number</em> archived log files. If there are more, the oldest archived
    211 log files will be deleted, only the latest <em>number</em> will be kept.
    212 By default, <em>number</em> is 10. </li>
    213  <li> <strong>s<em>filesize</em></strong>: next rotations will occur when
    214 <tt>current</tt> log files approach <em>filesize</em> bytes. By default,
    215 <em>filesize</em> is 99999; it cannot be set lower than 4096 or
    216 higher than 268435455. </li>
    217  <li> <strong>S<em>totalsize</em></strong>: next logdirs will contain up
    218 to <em>totalsize</em> bytes of archived (and maybe processed) log files. If
    219 archived log files take more space than that, the older ones are deleted
    220 until the total size fits. A <em>totalsize</em> of zero means no such limit;
    221 use <strong>n0</strong> instead if you don't want any archived log files. By
    222 default, <em>totalsize</em> is 0 (unlimited). </li>
    223  <li> <strong>l<em>tolerance</em></strong>: next rotations will be triggered
    224 when the size of <tt>current</tt> goes higher than <em>filesize</em> minus
    225 <em>tolerance</em>. <em>tolerance</em> cannot be more than half of
    226 <em>filesize</em>. By default, <em>tolerance</em> is 2000. </li>
    227  <li> <strong>r<em>cooldown</em></strong>: if an error occurs during operations
    228 on the next logdirs, retry every <em>cooldown</em> milliseconds. By default,
    229 <em>cooldown</em> is 2000; it's strongly discouraged to set it to a value
    230 under 50. </li>
    231  <li> <strong>E<em>alertsize</em></strong>: only the first <em>alertsize</em>
    232 bytes of the selected lines will be used in the next alerts. An
    233 <em>alertsize</em> of 0 means no limit. By default, <em>alertsize</em> is
    234 200. </li>
    235  <li> <strong>^<em>statussize</em></strong>: only the first <em>statussize</em>
    236 bytes of the selected lines will be used in the next status file updates.
    237 If a line is shorter than <em>statussize</em> bytes, the status file will be
    238 padded with newlines so it is always <em>statussize</em> bytes long. 0 means
    239 an unpadded, unlimited status file. By default, <em>statussize</em> is 1001. </li>
    240  <li> <strong>p<em>prefix</em></strong>: sets <em>prefix</em> as a prefix to be
    241 printed on every output line. For instance, a <tt>pfoobar:</tt> directive means
    242 that the next action directives should prepend every line with <tt>foobar:</tt>
    243 (plus a space) before outputting it. Note that a prefix is always printed
    244 <em>after</em> the timestamps, if any. To remove a prefix for the next action
    245 directives, use a standalone <tt>p</tt>. </li>
    246  <li> <strong>!<em>processor</em></strong>: registers
    247 <tt>execlineb -Pc <em>processor</em></tt> as a processor for the next logdirs;
    248 <tt>execlineb</tt> must be found in s6-log's PATH. This directive is only
    249 supported if s6 has been built with execline support; otherwise, it yields a
    250 syntax error at starting time.
    251 If <em>processor</em> is empty, no processor will be set for the next logdirs.
    252 By default, no processor is set. </li>
    253  <li> <strong>?<em>processor</em></strong>: registers
    254 <tt>/bin/sh -c <em>processor</em></tt> as a processor for the next logdirs.
    255 It is just like the <tt>!</tt> directive, except that the processor string
    256 is interpreted by <tt>/bin/sh</tt>, not <tt>execlineb</tt>. It is useful
    257 for people who want to build s6 without execline support. </li>
    258  <li> <strong>t</strong>: the logged line will be prepended with a
    259 <a href="//skarnet.org/software/skalibs/libstddjb/tai.html">TAI64N
    260 timestamp</a> (and a space) before being processed by the next action
    261 directive. Giving the <tt>t</tt> directive several times before an action
    262 directive has no effect. </li>
    263  <li> <strong>T</strong>: the selected line will be prepended with a
    264 <a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601
    265 timestamp</a> for combined date and time representing <em>local time</em>
    266 according to the system's timezone, with a space (not a 'T')
    267 between the date and the time and two spaces after the time, before being
    268 processed by the next action directive. Giving the <tt>T</tt> directive
    269 several times before an action directive has no effect. </li>
    270 </ul>
    271 
    272 <p>
    273  Note that unlike the other control directives, the <tt>t</tt> and
    274 <tt>T</tt> directives are <em>not sticky</em>: their effect will
    275 disappear after the next action directive, and they need to be
    276 reapplied if necessary. If both a <tt>t</tt> and a <tt>T</tt>
    277 directives are given before an action directive, the TAI64N timestamp
    278 will always appear before the ISO 8601 timestamp.
    279 </p>
    280 
    281 <h3> Action directives </h3>
    282 
    283 <p>
    284  These directives determine what s6-log actually <em>does</em> with the
    285 selected lines.
    286 </p>
    287 
    288 <ul>
    289  <li> <strong>2</strong>: alert. s6-log will print "s6-log: alert: ",
    290 possibly prepended with a timestamp, followed by the first
    291 <em>alertsize</em> bytes of the line, to its standard error. </li>
    292  <li> <strong>1</strong>: forward to stdout. s6-log will print the selected
    293 line to its stdout. If any error occurs, e.g. if stdout was a pipe and the
    294 reading end closed, this directive will be ignored for the rest of
    295 s6-log's lifetime. </li>
    296  <li> <strong>=<em>statusfile</em></strong>: status. s6-log will atomically
    297 update the <em>statusfile</em> file with the first <em>statussize</em>
    298 bytes of the line, and pad it with newlines. s6-log must have the right
    299 to write to <em>statusfile</em> and to <em>statusfile</em>'s directory. </li>
    300  <li> <strong><em>dir</em></strong> (must start with '/' or '.'): logdir.
    301 s6-log will log the line into the logdir <em>dir</em>. s6-log must have
    302 the right to write to <em>dir</em>.</li>
    303 </ul>
    304 
    305 
    306 <h2> Signals </h2>
    307 
    308 <ul>
    309  <li> SIGTERM: If s6-log has been run with the <tt>-p</tt> option, does nothing.
    310 Without this option, SIGTERM instructs s6-log to stop reading stdin after the
    311 next newline and exit after logging the last line. </li>
    312  <li> SIGALRM: triggers a rotation on every logdir s6-log is monitoring,
    313 as if the <tt>current</tt> file in those logdirs had reached the size
    314 limit. </li>
    315 </ul>
    316 
    317 <h2> Examples </h2>
    318 
    319 <pre>
    320      s6-log -b n20 s1000000 t /var/log/services/stuff
    321 </pre>
    322 
    323 <p>
    324  Logs all of stdin, prepending every line with a TAI64N timestamp, into the
    325 <tt>/var/log/services/stuff</tt> logdir, with a maximum archive of
    326 20 log files of 1 MB each; makes sure every line has been written
    327 before reading the next one.
    328 </p>
    329 
    330 <pre>
    331      s6-log n30 E500 - +fatal: 2 - +^STAT =/var/log/foobard/status f s10000000 S15000000 T !"gzip -nq9" /var/log/foobard
    332 </pre>
    333 
    334 <ul>
    335  <li> Sends alerts to stderr with the 500 first bytes of lines containing "fatal:". </li>
    336  <li> Maintains the <tt>/var/log/foobard/status</tt> file at 1001 bytes,
    337 updating it when it finds a log line starting with "STAT". </li>
    338  <li> Logs all other lines to logdir <tt>/var/log/foobard</tt>, prepending
    339 them with an ISO 8601 timestamp. When <tt>current</tt>
    340 reaches at least 9998 kB (i.e. 10 MB filesize minus 2kB tolerance), pipe it
    341 through <tt>gzip -nq9</tt> and save the result into a timestamped archive file, with
    342 a maximum of 30 such files or a total of 15 MB of compressed archive files. </li>
    343 </ul>
    344 
    345 
    346 <h2> Why use execlineb to interpret the "processor" string? </h2>
    347 
    348 <p>
    349  Because it is <em>exactly</em> what
    350 <a href="//skarnet.org/software/execline/execlineb.html">execlineb</a>
    351 is for.
    352 </p>
    353 
    354 <ul>
    355  <li> Directly executing <em>processor</em> is not flexible enough. We want
    356 to be able to run a complete command line, with an executable name and its
    357 arguments. </li>
    358  <li> We could interpret the <em>processor</em> string via <tt>/bin/sh</tt>.
    359 This is what <a href="https://cr.yp.to/daemontools/multilog.html">multilog</a>
    360 does. However, <tt>/bin/sh</tt>, despite being the traditional Unix interpreter,
    361 is overpowered for this. We don't need a complete shell script interpreter:
    362 most <em>processor</em> commands will be very simple, with only two or three
    363 words, and we only need a way to turn a string into an <em>argv</em>, i.e. a
    364 command line. </li>
    365  <li> <a href="//skarnet.org/software/execline/execlineb.html">execlineb</a>
    366 was designed just for this: to turn simple strings into command lines.
    367 It is a very fast and lightweight script launcher, that does not do any heavy
    368 startup initialization like <tt>/bin/sh</tt> does. It happens to be the perfect
    369 tool for the job. </li>
    370  <li> To be perfectly honest: I also did this on purpose so people have a
    371 reason to use the
    372 <a href="//skarnet.org/software/execline/">execline</a> language. But
    373 seriously, it <em>really</em> is the perfect tool for the job. </li>
    374 </ul>
    375 
    376 <h2> Why have another logging mechanism? </h2>
    377 
    378 <p>
    379  Because the syslog mechanism and all its implementations (save one) suck.
    380 I'm not being judgmental; I'm just stating the obvious.
    381 </p>
    382 
    383 <a name="diesyslogdiedie">
    384 <h3> The syslog design is flawed from the start </h3>
    385 </a>
    386 
    387 <p>
    388 <a href="https://blog.gerhards.net/2007/08/why-does-world-need-another-syslogd.html">When
    389 asked why he started rsyslog</a>, Rainer Gerhards came up with a lot of
    390 hand-waving and not a single word about technical points. There is a
    391 reason for that: rsyslog is forked from sysklogd! So, no matter how
    392 many bells and whistles are added to it, it still suffers from the same
    393 basic flaws.
    394 </p>
    395 
    396 <p>
    397  The problem with syslogd does not come from such or such implementation.
    398 The problem comes from syslog's <em>design</em> in the first place.
    399 </p>
    400 
    401 <ul>
    402  <li> syslog makes you send <em>all</em> your logs to the same place.
    403 The logs from a zillion processes are read by a single syslogd server.
    404 The server checks log lines against system-wide regular expressions
    405 to decide where to write them. This raises the following issues:
    406  <ul>
    407   <li> Unless the client explicitly mentions its name in every log
    408 line, there is no way for log readers to know what process generated a
    409 given line. Some syslogd implementations can log the pid of the client;
    410 big deal. </li>
    411   <li> Log lines from every client have to run through the same regular
    412 expression matching. This requires huge regular expression sets, and an
    413 obvious performance impact, to do anything meaningful. And as a matter
    414 of fact, standard syslogd configurations don't do anything meaningful:
    415 they separate the logs into a few streams such as <tt>/var/log/messages</tt>,
    416 <tt>/var/log/auth.log</tt>, <tt>/var/log/daemon.log</tt> or
    417 <tt>/var/log/syslog</tt> with very vague semantics. All of syslogd's
    418 line processing power remains unused, because making real use of it would
    419 be too complex. </li>
    420  </ul>
    421  <li> syslogd logs to <em>files</em>. This is wrong, because files grow
    422 and disks fill up. Sure, there are utilities such as <tt>logrotate</tt>
    423 to perform cleaning up, but as long as logging and log rotation are
    424 kept separate, there is a race condition: a log file can grow and fill
    425 up a disk before a rotation occurs. I am all for separating tasks that
    426 can be separated, but there is no choice here: <em>logging and log
    427 rotation management must be done <strong>by the same tool</strong></em>.
    428 Only a few non-mainstream implementations of syslogd do this, including the
    429 <a href="https://busybox.net/">Busybox</a> one - and that is a
    430 feature added by the Busybox developers who are aware of the problem
    431 but want to maintain compatibility with the historical syslogd.
    432 Neither syslogd (-ng or not) nor rsyslogd manages its log files: that's a
    433 flaw that no amount of external tools is going to fix. </li>
    434  <li> syslogd is a complex process that runs as root. We all know what
    435 complex processes running as root mean: bugs turning into security holes. </li>
    436  <li> syslog requires a syslogd service, and fails otherwise. A syslogd
    437 service may not be present, it may fail... or it may want to log stuff.
    438 Who's going to take care of syslogd's error messages? </li>
    439 </ul>
    440 
    441 <p>
    442  syslog is slow, it's unsafe, and it's incomplete. The only reason people
    443 use it is because it's historical, it exists, and there hasn't been any
    444 serious alternative yet, except maybe
    445 <a href="https://cr.yp.to/daemontools/multilog.html">multilog</a>, which
    446 s6-log improves upon.
    447 </p>
    448 
    449 <a name="loggingchain">
    450 <h3> A not-so-modest proposal: the logging chain </h3>
    451 </a>
    452 
    453 <p>
    454  Unix distributions already do this to some extent, but it's at best
    455 unclear where the logs go for any given program.
    456 </p>
    457 
    458 <ul>
    459  <li> Every program, without exception, should send its logs (be it
    460 error messages, warning messages, or anything) to its <em>standard
    461 error descriptor</em>, i.e. fd 2. <em>This is why it's open for.</em> </li>
    462  <li> When process 1 starts, the logging chain is rooted to the
    463 <em>machine console</em>: anything process 1 sends to its stderr
    464 appears, without modification, on the machine console, which should
    465 at any time remain the last resort place where logs are sent. </li>
    466  <li> Process 1 should spawn and supervise a <em>catch-all logging
    467 mechanism</em> that handles logs from every service that does not
    468 take care of its own logging. Error messages from this logging
    469 mechanism naturally go to the machine console. </li>
    470  <li> Process 1's own error messages can go to the machine console,
    471 or <a href="s6-svscan-1.html#log">dirty tricks can be used</a> so they
    472 go to the catch-all logging mechanism. </li>
    473  <li> Services that are spawned by process 1 should come with their
    474 own logger service; the supervision mechanism offered by
    475 <a href="s6-svscan.html">s6-svscan</a> makes it easy. Error messages
    476 from the loggers themselves naturally go to the catch-all
    477 mechanism. </li>
    478  <li> User login mechanisms such as <tt>getty</tt>, <tt>xdm</tt> or
    479 <tt>sshd</tt> are services: they should be started with their own
    480 loggers. Of course, when a user gets a terminal and a shell, the
    481 shell's stderr should be redirected to the terminal: interactive
    482 programs break the automatic logging chain and delegate responsibility
    483 to the user. </li>
    484  <li> A syslogd service <em>may</em> exist, to catch logs sent via
    485 syslog() by legacy programs. But it is a normal service, and logs
    486 caught by this syslogd service are not part of the logging chain.
    487  It is probably overkill to provide the syslogd service with its own
    488 logger; error messages from syslogd can default to the catch-all logger.
    489  The s6 package, including the <a href="ucspilogd.html">ucspilogd</a> program,
    490 provides enough tools to easily implement
    491 a complete syslogd system, for a small fraction of the resource needs and
    492 the complexity of native syslogd implementations. </li>
    493 </ul>
    494 
    495 <p>
    496  So, given a program, where are its logs sent&nbsp;?
    497 </p>
    498 
    499 <ul>
    500  <li> Logs sent via syslog() will be handled by the syslogd service as
    501 usual. Smart administrators will make sure that those ones are as few as
    502 possible. The rest of this analysis is about logs sent to stderr. </li>
    503  <li> If the program is descended from a user's interactive program,
    504 its logs are sent to the user's terminal or the user's choice redirection
    505 target. </li>
    506  <li> If the program is descended from a logged service, its logs are
    507 naturally sent to the service's logger. </li>
    508  <li> Else the logs are sent to the catch-all logger. </li>
    509  <li> Only the catch-all logger's error messages, the kernel's fatal
    510 error messages, and maybe process 1's error messages, are sent to the
    511 system console. </li>
    512 </ul>
    513 
    514 <a name="howtouse">
    515 <h3> What does s6-log have to do with all this? </h3>
    516 </a>
    517 
    518 <p>
    519  In a <em>logging chain</em> situation, every service must have
    520 its own logger. To avoid syslogd's design mistakes, one logger process
    521 per service must be run. s6-log fits that role. Using s6-log as
    522 your one-stop logger offers the following benefits:
    523 </p>
    524 
    525 <ul>
    526  <li> Every instance of s6-log can run as a different user, so it's
    527 easy to give different access rights to different logs. It is also
    528 more secure not to have any logger process running as root. </li>
    529  <li> s6-log consumes very little memory per instance (unless it
    530 accumulates unflushed log lines, which you can avoid with the
    531 <tt>-b</tt> option). So, launching a lot of s6-log processes does
    532 not waste resources. </li>
    533  <li> s6-log is vastly configurable via logging scripts; every instance
    534 is as powerful as a traditional syslogd. </li>
    535  <li> s6-log can log to a RAM filesystem and thus is suitable as a
    536 catch-all logger. Clever tricks like Upstart's <em>logd</em> or daemontools'
    537 <a href="https://cr.yp.to/daemontools/readproctitle.html">readproctitle</a>
    538 are just that: tricks. s6-log gives a unified interface to all of
    539 your system's loggers. </li>
    540 </ul>
    541 
    542 
    543 <a name="network">
    544 <h3> You're wrong about being as powerful as
    545 syslogd: s6-log does not do remote logging. </h3>
    546 </a>
    547 
    548 <p>
    549  You mean you want to send, <em>live</em>, every <em>log line</em>
    550 over the network via <em>UDP</em>&nbsp;? You can't be serious.
    551 </p>
    552 
    553 <p>
    554  Do yourself a favor and use s6-log to write log lines to a logdir,
    555 with a processor script that sends files-being-archived to the
    556 network, possibly after compressing them. More reliability, less
    557 log lines lost, less network traffic, better engineering. If you
    558 have no disk to even write the <tt>current</tt> files to, write
    559 to a small RAM filesystem.
    560 </p>
    561 
    562 <p>
    563  If you <em>have to</em> log stuff <em>live</em> via the network, you
    564 do not need any local logging software. You don't even need syslogd.
    565 Just filter your stderr via some <tt>grep</tt> that selects lines for
    566 you, then sends them to a network socket. A trivial shell script, or
    567 <a href="//skarnet.org/software/execline/">execline</a>
    568 script, can do that for you.
    569 </p>
    570 
    571 <p>
    572  Do not insist on using syslogd. It does nothing magical, and nothing
    573 that can't be done in a simpler way using simpler tools.
    574 </p>
    575 
    576 </body>
    577 </html>