Como implementar a funcionalidade do logwatch no início do diário do systemd?

6

O Logwatch varre arquivos de log com intervalos regulares, coleta erros e outras coisas, e os envia para o administrador. Isso estava de volta nos dias de syslog e logfiles. Qual é a solução correspondente para o diário do systemd?

    
por lkraav 27.12.2013 / 20:16

2 respostas

3

Baseado no post do @Siosm eu criei uma ferramenta com a qual você pode escrever uma configuração simples com padrões, e então você é notificado sobre tudo que não combina com esses padrões: journalwatch.

Você pode encontrar mais informações no Thread de fórum do Archlinux .

Parece que há também um patch e um hack disponível no rastreador do logwatch agora.

    
por 11.07.2014 / 14:19
2

Tanto quanto eu sei, não há substituto para a funcionalidade de logwatch a partir de hoje. No entanto, é muito fácil para alguém fazer isso usando o módulo de python systemd.journal .

Eu escrevi uma postagem no blog com com um exemplo meses atrás.

Exemplo:

#!/usr/bin/env python3

from systemd import journal
from datetime import datetime,timedelta
import re
import smtplib
from email.mime.text import MIMEText

# First, let's define patterns to ignore.

# Those are for matching dynamically named units:
session = re.compile("session-[a-z]?\d+.scope")
sshUnit = re.compile("sshd@[0-9a-f.:]*")

# Those will match the logged message itself:
sshSocketStart = re.compile("(Strating|Stopping) OpenSSH Per-Connection Daemon.*")
sshAcceptPublicKey = re.compile("Accepted publickey for (bob|alice).*")
sshReceivedDisconnect = re.compile("Received disconnect from.*")
logindNewSession = re.compile("New session [a-z]?\d+ of user (bob|alice).*")
sshdSessionClosed = re.compile(".*session closed for user (bob|alice).*")
sessionOpenedRoot = re.compile(".*session opened for user root.*")
suSessionClosedGit = re.compile(".*session opened for user git.*")
anacronNormalExit = re.compile("Normal exit (\d+ jobs run).*")
postfixStatistics = re.compile("statistics:.*")
postfixHostnameDoesNotResolve = re.compile("warning: hostname .* does not resolve to address .*: Name or service not known")

# Open the journal for reading, set log level and go back one day and 10 minutes
j = journal.Reader()
j.log_level(journal.LOG_INFO)
yesterday = datetime.now() - timedelta(days=1, minutes=10)
j.seek_realtime(yesterday)

# We'll store messages in this variable
mailContent = []

# Filter and store output
for entry in j:
    # Special cases for logs without a message
    if 'MESSAGE' not in entry:
        mailContent.append( 'U %s %s[%s]: EMPTY!' % (
            datetime.ctime(entry['__REALTIME_TIMESTAMP']),
            entry['PRIORITY'],
            entry['SYSLOG_IDENTIFIER'],
        ))

    # With systemd unit name
    elif '_SYSTEMD_UNIT' in entry:
        if entry['PRIORITY'] > 4:
            if entry['_SYSTEMD_UNIT'] == "wtcomments.service":
                pass
            elif entry['_SYSTEMD_UNIT'] == "ffsync.service":
                pass
        elif session.match(entry['_SYSTEMD_UNIT']):
            pass
        elif sshUnit.match(entry['_SYSTEMD_UNIT']):
            if sshAcceptPublicKey.match(entry['MESSAGE']):
                pass
            elif sshReceivedDisconnect.match(entry['MESSAGE']):
                pass
        elif entry['_SYSTEMD_UNIT'] == "systemd-logind.service":
            if logindNewSession.match(entry['MESSAGE']):
                pass
        elif entry['_SYSTEMD_UNIT'] == "postfix.service":
            if postfixHostnameDoesNotResolve.match(entry['MESSAGE']):
                pass
        else:
            mailContent.append( 'U %s %s %s %s[%s]: %s' % (
                datetime.ctime(entry['__REALTIME_TIMESTAMP']),
                entry['PRIORITY'],
                entry['_SYSTEMD_UNIT'],
                entry['SYSLOG_IDENTIFIER'],
                entry['_PID'],
                entry['MESSAGE']
            ))

    # With syslog identifier only
    elif entry['SYSLOG_IDENTIFIER'] == "systemd":
        if sshSocketStart.match(entry['MESSAGE']):
            pass
        elif firewalldStart.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "sshd":
        if sshdSessionClosed.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "sudo":
        if sessionOpenedRoot.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "CROND":
        if sessionOpenedRoot.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "anacron":
        if anacronNormalExit.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "postfix/anvil":
        if postfixStatistics.match(entry['MESSAGE']):
            pass
    elif entry['SYSLOG_IDENTIFIER'] == "su":
        if suSessionClosedGit.match(entry['MESSAGE']):
            pass
    else:
        mailContent.append( 'S %s %s %s: %s' % (
            datetime.ctime(entry['__REALTIME_TIMESTAMP']),
            entry['PRIORITY'],
            entry['SYSLOG_IDENTIFIER'],
            entry['MESSAGE']
        ))

# Send the content in a mail to root
mail = MIMEText('\n'.join(mailContent))
mail['Subject'] = '[example.com] Logs from ' + datetime.ctime(yesterday) + ' to ' + datetime.ctime(datetime.now())
mail['From'] = '[email protected]'
mail['To'] = '[email protected]'
server = smtplib.SMTP('localhost')
server.send_message(mail)
server.quit()
    
por 12.05.2014 / 02:08