1. Introduction
  2. Example for a given day
  3. Configuration
  4. Biggest advantages
  5. Feedback

1. Introduction

I got burned by logrotate killing something while rotating logs a few years ago, so now I use rsyslog plus a much simpler setup for log rotation.

Rsyslog can use templates to create dated logfiles, so I restart rsyslog at midnight and hard-link new /var/log/YYYY/MMDD files to the same names under /var/log:

me% ls -liF /var/log /var/log/2026/0419
/var/log:
 78649 drwxr-s--- 111 root wheel    111 19-Apr-2026 00:00:00 2026/
137805 -rw-r-----   2 root wheel 168267 19-Apr-2026 07:04:00 cron
137810 -rw-r-----   2 root wheel    101 19-Apr-2026 00:01:00 daemon
137822 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 debug.log
137814 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local0log
137815 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local1log
137816 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local2log
137817 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local3log
137818 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local4log
137819 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local5log
137820 -rw-r-----   2 root wheel  83366 19-Apr-2026 06:36:20 local6log
137821 -rw-r-----   2 root wheel    194 19-Apr-2026 00:02:00 local7log
137811 -rw-r-----   2 root wheel   3951 19-Apr-2026 03:04:00 maillog
137813 -rw-r-----   2 root wheel    140 19-Apr-2026 06:22:28 ntplog
137809 -rw-r-----   2 root wheel    359 19-Apr-2026 06:49:33 secure
137806 -rw-r-----   2 root wheel   8880 19-Apr-2026 07:00:00 syslog

/var/log/2026/0419:
137805 -rw-r-----   2 root wheel 168267 19-Apr-2026 07:04:00 cron
137810 -rw-r-----   2 root wheel    101 19-Apr-2026 00:01:00 daemon
137822 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 debug.log
137814 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local0log
137815 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local1log
137816 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local2log
137817 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local3log
137818 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local4log
137819 -rw-r-----   2 root wheel     37 19-Apr-2026 00:00:00 local5log
137820 -rw-r-----   2 root wheel  83366 19-Apr-2026 06:36:20 local6log
137821 -rw-r-----   2 root wheel    194 19-Apr-2026 00:02:00 local7log
137811 -rw-r-----   2 root wheel   3951 19-Apr-2026 03:04:00 maillog
137813 -rw-r-----   2 root wheel    140 19-Apr-2026 06:22:28 ntplog
137809 -rw-r-----   2 root wheel    359 19-Apr-2026 06:49:33 secure
137806 -rw-r-----   2 root wheel   8880 19-Apr-2026 07:00:00 syslog

2. Example for a given day

At midnight today (19 Apr 2026) this happened:

a: Stop rsyslogd

b: Create the /var/log/2026/0419 directory with new logfiles

c: Since the corresponding /var/log files are linked to the previous day, I can delete them and link to the new ones (basic code without error checks):

cd /var/log || exit 1
mkdir -p /var/log/2026/0419 || exit 2

for file in cron daemon local0log local1log local2log local3log \
            local4log local5log local6log local7log maillog ntplog \
            secure syslog
do
    rm $file
    touch 2026/0419/$file
    ln 2026/0419/$file
done

d: Restart rsyslogd

3. Configuration

Trimmed version of my FreeBSD /usr/local/etc/rsyslog.conf:

#### MODULES =====================================================
#
module(load="immark" interval="3600")   # Write MARK messages hourly
module(load="imuxsock") # Local system logging (logger, etc)
module(load="imklog")   # Kernel logging (previously done by rklogd)

#module(load="imudp")    # Provides UDP syslog reception
#$UDPServerRun 514

#module(load="imtcp")    # Provides TCP syslog reception
#$InputTCPServerRun 514

#### GLOBAL DIRECTIVES ===========================================

# Enable rsyslogd writing all mark messages
$ActionWriteAllMarkMessages on
:programname, isequal, "rsyslogd"

# Use short timestamp format
## $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
$ActionFileDefaultTemplate ShortForm

# Use high-precision timestamps and timezone information
## $ActionFileDefaultTemplate RSYSLOG_FileFormat

# File syncing capability is disabled by default.  This feature is
# usually not required, not useful and an extreme performance hit
## $ActionFileEnableSync on

#### TEMPLATES ===================================================

$template DYNauth,"/var/log/%$YEAR%/%$MONTH%%$DAY%/secure"
$template DYNcron,"/var/log/%$YEAR%/%$MONTH%%$DAY%/cron"
$template DYNdaemon,"/var/log/%$YEAR%/%$MONTH%%$DAY%/daemon"
...

# This is identical to traditional format, without the hostname.
$template ShortForm,"%timegenerated% %syslogtag%%msg%\n"

#### RULES =======================================================

# ----------------------------------------------------------------
# Daemon messages.

if ($syslogfacility-text == 'daemon') then {
    ?DYNdaemon
    stop
}

# ----------------------------------------------------------------
# The auth and security files have restricted access.
## authpriv.*     /var/log/secure
## auth.*         /var/log/secure
## security.*     /var/log/secure

if ($syslogseverity <= '6') then {
    if ($syslogfacility-text == 'auth' or
        $syslogfacility-text == 'authpriv' or
        $syslogfacility-text == 'security')
    then {
        ?DYNauth
        stop
    }
}

# ----------------------------------------------------------------
# Log cron stuff
## cron.*          /var/log/cron

if ($syslogseverity <= '6' and
    $syslogfacility-text == 'cron') then {
    ?DYNcron
    stop
}

The complete rsyslog.conf file is located here.

The "DYNcron" template stores 19 Apr 2026 cron entries in /var/log/2026/0419/cron. You don't actually have to create the directories (rsyslog does it), but it won't put anything in the new logfiles until there's an explicit call to "logger" or the equivalent -- since I'm restarting logging anyways, it's simpler to just do it myself.

4. Biggest advantages

Hope this is useful.

5. Feedback

Feel free to send comments.


Generated from article.t2t by txt2tags
$Revision: 1.2 $
$UUID: cff22cb1-2dcb-3eb9-9b69-e9f023df87b6 $