SyslogScan::Daemon - Watch log files


 syslogscand [-f] [-c config] {start|stop|reload|restart|check}

 @ISA = qw(SyslogScan::Daemon);



SyslogScan::Daemon is a framework on which to hang log file watchers. SyslogScan::Daemon is a subclass of Daemon::Generic and uses Plugins to create the framework.


The configuration prefix for plugins for SyslogScan::Daemon is ''. Use plugin to load plugins.


SyslogScan::Daemon defines the following configuration parameters which may be given in indented lines that follow plugin SyslogScan::Daemon or anywhere in the configuration file.


(default 0) Turn on debugging.


(default /etc/syslogscand.conf). The location of the configuration file for the plugins or SyslogScan::Daemon.


Plugins for SyslogScan::Daemon should subclass SyslogScan::Daemon::Plugin. The following methods will be invoked by SyslogScan::Daemon:


Called from Plugins and %args will come from the configuration file. An object of the type of the plugin is expected as the return value. It's okay to die here.


Called right after new() and when a reload is requested. Return value is a %hash that is then passed into postconfig(). It's okay to die here.


Called after all plugin's preconfig()s are called. No return value is expected.


Called after postconfig(). The return value of get_logs() is a hash: the keys are log file names and the values are lists of regular expressions to match. For example:

 sub get_logs
        return (
                '/var/log/mail.log'     => [
                        qr{postfix/smtp\[\d+\]: \w+: to=<([^@]+@([^>]+))>, .*, status=(bounced).*\b(?i:blacklist(ed)?|spamming|spam list|removal|remove|block list|blocked for abuse)\b},
                        qr{postfix/smtp\[\d+\]: \w+: to=<([^@]+@([^>]+))>, .*, status=(deferred).*Rejected: \S+ listed at http},

The default implementation of get_logs() checks to see if there is a $self-{plugins}> member and if there is, it re-dispatches the get_logs() call to its plugins. It keeps track of the regular expressions returned by its plugins that in matched_line(), callbacks can be redistributed to the appropriate plugin:

 sub matched_line
        my ($self, $logfile, $rx) = @_;

        for my $plugin (@{$self->{logs}{$logfile}{$rx}}) {
                my @ret = $plugin->invoke('parse_logs', $logfile, $rx);

                # your stuff here...
matched_line($file, $rx)

Called after one of the regular expressions returned by get_logs() matched a log line. The arguments are the log filename where the match was found and the regular expression that matched. Passed implicitly are the line that was matched ($_) and any of the numbered regular expression submatches ($1, $2, etc). No return value is expected.


Called once per second or so (or however of the config file says).

The default implementation of periodic() checks to see if there is a $self-{plugins}> member and if there is calls $self-{plugins}->invoke('periodic')> to send the heartbeat down the plugin tree.

Use Plugins::SimpleConfig

Using Plugins::SimpleConfig to write the plugins make the job much easier.

Plugins that have plugins

For plugins that in turn have plugins, a helper function is provided in SyslogScan::Daemon::Plugin:

 sub set_api
        my ($self, $ssd_configfile, @api) = @_;

        my $config = $self->{configfile} || $ssd_configfile;

        $self->{myapi} = Plugins::API->new;
        $self->{myapi}->register(undef, parentapi => sub { return $self->{api} });

        $self->{plugins} = new Plugins context => $self->{context};
        $self->{plugins}->readconfig($config, self => $self);


        $self->{plugins}->invoke('preconfig', $config);

To use it, define your preconfig() as follows:

 sub preconfig
        my ($self, $ssd_configfile, @api) = @_;

                stuff for Plugins::API::api()

        ... more initialization if needed


Plugins Plugins::Style1 Plugins::API SyslogScan::Daemon::BlacklistDetector SyslogScan::Daemon::SpamDetector


Copyright (C) 2006, David Muir Sharnoff <> This module may be used and copied on the same basis as Perl itself.

If you find this useful, please thank me by giving me a chance to bid on your next Internet transit purchase of T1 or larger. I have good prices for T1s, T3s, OC3s and such. Thank you.