Search code examples
rsyslograinerscript

How to save files found with wildcard file & folder to the right file name on the central server with rsyslog?


I am trying to use rainerscript and rsyslog v8.38 to grab logs off my servers by both wildcard and wildcard files in wildcard folders, and then save them in the same folder structure at the far end. I have wildcards working thanks to the article here, but I'm trying to extend this concept to work for the wildcard folders as well.

Currently I collect the files from the folders correctly, but once it's saved the lines from all the files are saved in to one file for each folder, named the same as the folder is, for example, if I do this on my server:

echo "TEST1" >> /srv/log/test-new/test.log
echo "TEST1" >> /srv/log/test-new/test-new.log

I end up with this on my central server:

# cat /srv/rsyslog/2018/HOSTNAME/10/26/test-new

<133>2018-10-26T15:32:37.975449+00:00 HOSTNAME  test-new/test.log nested-srv-logs TEST1
<133>2018-10-26T15:32:51.042633+00:00 HOSTNAME  test-new/test-new.log nested-srv-logs TEST1

I was hoping that I could have the files saved on the central server in the same folder structure as they were found on the sending machine, is this possible?

My config is as below, sending machine has:

module(load="omrelp")
module(load="omfwd")

template(name="CustomForwardFormat" type="list") {
    constant(value="<")
    property(name="pri")
    constant(value=">")
    property(name="timestamp" dateFormat="rfc3339")
    constant(value=" ")
    property(name="hostname")
    constant(value=" ")
    property(name=".suffix")
    constant(value=" ")
    property(name="syslogtag" position.from="1" position.to="32")
    property(name="msg" spifno1stsp="on" )
    property(name="msg")
    constant(value="\n")
    }

ruleset(name="sendToLogserver") {
    action(type="omrelp" Target="rsyslog" Port="25014" template="CustomForwardFormat"
    queue.type="LinkedList" queue.size="10000" queue.filename="q_sendToLogserver" queue.highwatermark="9000"
    queue.lowwatermark="50" queue.maxdiskspace="500m" queue.saveonshutdown="on" action.resumeRetryCount="-1"
    action.reportSuspension="on" action.reportSuspensionContinuation="on" action.resumeInterval="10")
}

ruleset(name="sendToJsonLogserver") {
    action(type="omfwd" protocol="tcp" Target="logstash" Port="5114" template="RSYSLOG_SyslogProtocol23Format"
    queue.type="LinkedList" queue.size="10000" queue.filename="q_sendToJsonLogserver" queue.highwatermark="9000"
    queue.lowwatermark="50" queue.maxdiskspace="500m" queue.saveonshutdown="on" action.resumeRetryCount="-1"
    action.reportSuspension="on" action.reportSuspensionContinuation="on" action.resumeInterval="10")
}

input(type="imfile"
    File="/srv/log/*.log"
        Tag="srv-logs"
        Ruleset="srv_logs"
        addMetadata="on")

input(type="imfile"
    File="/srv/log/*/*.log"
        Tag="nested-srv-logs"
        Ruleset="srv_logs"
        addMetadata="on")

ruleset(name="srv_logs") {
    # http://www.rsyslog.com/doc/v8-stable/rainerscript/functions.html
          # re_extract(expr, re, match, submatch, no-found)
    set $.suffix=re_extract($!metadata!filename, "(.*)/([^/]*)", 0, 2, "unknown.log");
    if ( $programname == "nested-srv-logs" ) then {
      set $.sub-suffix=re_extract($!metadata!filename, "(.*)/([^/]*)/(.*)", 0, 2, "unknown.log");
        set $.suffix=$.sub-suffix & "/" & $.suffix;
    }
    if( $!metadata!filename contains 'json' ) then {
            call sendToJsonLogserver
    } else {
      call sendToLogserver
    }
    stop
}

Central server has:

module(load="imrelp")
input(type="imrelp" port="25014" ruleset="RemoteLogProcess")

module(load="builtin:omfile" FileOwner="syslog" FileGroup="syslog" dirOwner="syslog" dirGroup="syslog" FileCreateMode="0644" DirCreateMode="0755")

template(name="CustomForwardFormat" type="list") {
    constant(value="<")
    property(name="pri")
    constant(value=">")
    property(name="timestamp" dateFormat="rfc3339")
    constant(value=" ")
    property(name="hostname")
    constant(value=" ")
    property(name=".suffix")
    constant(value=" ")
    property(name="syslogtag" position.from="1" position.to="32")
    property(name="msg" spifno1stsp="on" )
    property(name="msg")
    constant(value="\n")
    }

$EscapeControlCharactersOnReceive off

template(name="FloowLogSavePath" type="list") {
    constant(value="/srv/rsyslog/")
    property(name="timegenerated" dateFormat="year")
    constant(value="/")
    property(name="hostname")
    constant(value="/")
    property(name="timegenerated" dateFormat="month")
    constant(value="/")
    property(name="timegenerated" dateFormat="day")
    constant(value="/")
    property(name="$.logpath" )
}

ruleset(name="RemoteLogProcess") {
    # For facilities local0-7 set log filename from $programname field: replace __ with /
    if ( $syslogfacility >= 16 ) then
    {
        set $.logpath = replace($programname, "__", "/");
        action(type="omfile" dynaFileCacheSize="1024" dynaFile="FloowLogSavePath" template="CustomForwardFormat"
        flushOnTXEnd="off" asyncWriting="on" flushInterval="1" ioBufferSize="64k")
    } else {
        if (($syslogfacility == 0)) then {
            set $.logpath = "kern.log";
        } else if (($syslogfacility == 1)) then {
            set $.logpath = "user";
        } else if (($syslogfacility == 2)) then {
            set $.logpath = "mail";
        } else if (($syslogfacility == 3)) then {
            set $.logpath = "daemon";
        } else if (($syslogfacility == 4) or ($syslogfacility == 10)) then {
            set $.logpath = "auth.log";
        } else if (($syslogfacility == 9) or ($syslogfacility == 15)) then {
            set $.logpath = "cron";
        } else {
            set $.logpath ="syslog";
        }
        # Built-in template RSYSLOG_FileFormat: High-precision timestamps and timezone information
        action(type="omfile" dynaFileCacheSize="1024" dynaFile="FloowLogSavePath" template="CustomForwardFormat"
        flushOnTXEnd="off" asyncWriting="on" flushInterval="1" ioBufferSize="64k")
    }
}

Solution

  • After checking my config, my previous answer was incorrect, in order to get wildcard folders working correctly I did the following:

    Sender:

    input(type="imfile"
        File="/srv/log/*.log"
        Tag="srv-logs"
        Ruleset="send_sorted"
        addMetadata="on")
    
    input(type="imfile"
        File="/srv/log/*/*.log"
        Tag="nested-srv-logs"
        Ruleset="send_sorted"
        addMetadata="on")
    
    module(load="omrelp")
    
    ruleset(name="send_sorted") {
        set $.suffix=substring($!metadata!filename, 9, 150);
        if( $!metadata!filename contains 'json' ) then {
          call sendToJsonLogserver
        } else {
          call sendToLogserver
        }
        stop
    }
    
    template(name="CustomForwardFormat" type="list") {
        constant(value="<")
        property(name="pri")
        constant(value=">")
        property(name="timestamp" dateFormat="rfc3339")
        constant(value=" ")
        property(name="hostname")
        constant(value=" ")
        property(name=".suffix")
        constant(value=" ")
        property(name="syslogtag")
        property(name="msg" spifno1stsp="on" )
        property(name="msg")
        constant(value="\n")
        }
    ruleset(name="sendToLogserver") {
        action(type="omrelp"
               target="rsyslog"
               port="25014"
               template="CustomForwardFormat"
               queue.type="LinkedList" 
               queue.size="10000"
               queue.filename="q_sendToLogserver"
               queue.highwatermark="9000"
               queue.lowwatermark="50"
               queue.maxdiskspace="500m"
               queue.saveonshutdown="on" 
               action.resumeRetryCount="-1"
               action.reportSuspension="on"
               action.reportSuspensionContinuation="on"
               action.resumeInterval="10")
    }
    
    ruleset(name="sendToJsonLogserver") {
        action(type="omfwd" 
               target="logstash" 
               protocol="tcp" 
               port="5114" 
               template="RSYSLOG_SyslogProtocol23Format"
               queue.type="LinkedList"
               queue.size="10000"
               queue.filename="q_sendToJsonLogserver"
               queue.highwatermark="9000"
               queue.lowwatermark="50"
               queue.maxdiskspace="500m" 
               queue.saveonshutdown="on"
               action.resumeRetryCount="-1"
               action.reportSuspension="on"
               action.reportSuspensionContinuation="on"
               action.resumeInterval="10")
    }  
    

    On my central server:

    module(load="imrelp")
    input(type="imrelp" port="25014" ruleset="RemoteLogProcess")
    
    module(load="builtin:omfile" FileOwner="syslog" FileGroup="syslog" dirOwner="syslog" dirGroup="syslog" FileCreateMode="0644" DirCreateMode="0755")
    
    template(name="CustomForwardFormat" type="list") {
        constant(value="<")
        property(name="pri")
        constant(value=">")
        property(name="timestamp" dateFormat="rfc3339")
        constant(value=" ")
        property(name="hostname")
        constant(value=" ")
        property(name=".suffix")
        constant(value=" ")
        property(name="syslogtag")
        property(name="msg" spifno1stsp="on" )
        property(name="msg")
        constant(value="\n")
        }
    
    template(name="FloowLogSavePath" type="list") {
        constant(value="/srv/rsyslog/")
        property(name="timegenerated" dateFormat="year")
        constant(value="/")
        property(name="hostname")
        constant(value="/")
        property(name="timegenerated" dateFormat="month")
        constant(value="/")
        property(name="timegenerated" dateFormat="day")
        constant(value="/")
        property(name=".logpath")
    }
    
    template(name="extract" type="string" string="%syslogtag%")
    
    ruleset(name="RemoteLogProcess") {
        if ( $syslogfacility >= 16 ) then
        {
            set $.logpath = exec_template("extract");
            action(type="omfile" 
                   dynaFileCacheSize="1024" 
                   dynaFile="FloowLogSavePath" 
                   template="CustomForwardFormat"
                   flushOnTXEnd="off"
                   asyncWriting="on"
                   flushInterval="1" 
                   ioBufferSize="64k")
        } else {
            if (($syslogfacility == 0)) then {
              set $.logpath = "kern.log";
            } else if (($syslogfacility == 1)) then {
                set $.logpath = "user";
            } else if (($syslogfacility == 2)) then {
                set $.logpath = "mail";
            } else if (($syslogfacility == 3)) then {
                set $.logpath = "daemon";
            } else if (($syslogfacility == 4) or ($syslogfacility == 10)) then {
                set $.logpath = "auth.log";
            } else if (($syslogfacility == 9) or ($syslogfacility == 15)) then {
                set $.logpath = "cron";
            } else {
                set $.logpath ="syslog";
            }
            action(type="omfile"
                   dynaFileCacheSize="1024"
                   dynaFile="FloowLogSavePath"
                   template="CustomForwardFormat"
                   flushOnTXEnd="off"
                   asyncWriting="on"
                   flushInterval="1"
                   ioBufferSize="64k")
        }
    }