Script archiviazione log in Python

python-logUna delle operazione più comuni è quella di archiviazione e compressione dei log. I file di log sono una risorsa fondamentale per il controllo delle procedure, ma un software che scrive log in maniera incontrollata (ad esempio per un bug della procedura che lo manda in loop infinito) può essere pericoloso. A volte può non bastare impostare un filsystem quota, in quanto anche riempiendo tutto lo spazio a disposizione, lo script risulterebbe comunque bloccato e potrebbe compromettere altri script che girano con lo stesso utente.
Vediamo quindi una semplice procedura per comprimere ed archiviare i file di log applicativi (Nota: per i log di sistema continueremo ad usare syslogd).

Per rendere più generale lo script faremo in modo di passargli come argomento la directory in cui si trovano i log, la directory di archiviazione e il numero di mesi per cui intendiamo conservare i log in formato non compresso. Possiamo utilizzare il modulo argparse in questo modo:

import argparse
parser = argparse.ArgumentParser(description='Log rotate utility')
parser.add_argument(dest='logdir',metavar='logdir')
parser.add_argument(dest='archivedir',metavar='archivedir')
parser.add_argument(dest='monthsback',metavar='monthsback')
args = parser.parse_args()
LOGDIR = args.logdir
ARCHIVEDIR = args.archivedir
MONTHSBACK = -int(args.monthsback)

Il modulo provvederà automaticamente a comunicare all’utente che è necessario specificare tutti gli argomenti.
Ora recuperiamo l’elenco delle cartella che vogliamo comprimere:

subdirectories = os.listdir(LOGDIR)

Attenzione che il comando in oggetto vi restituirà l’elenco dei file nella cartella, se volete selezionare solo le cartelle dovete verificare singolarmente se si tratta di una directory o di un file.
In questo particolare caso le cartelle sono suddivise per mese e anno, e sono nominate nel seguente modo “2015-09”. Quindi, trasformiamo la stringa in un oggetto di tipo datetime per usarlo successivamente per controllare se è dentro il range di periodo per l’archiviazione o meno:

log_folder_datetime = datetime.strptime(folder, "%Y-%m")

Ora, utilizziamo il modulo dateutil per calcolare l’oggetto datetime relativo all’inizio del periodo di archiviazione indicato:

log_rotate_datetime = datetime.today() + relativedelta(months=MONTHSBACK)

Ora, dopo aver controllato se la cartella in oggetto deve essere archiviata, procediamo alla compressione:

shutil.make_archive(os.path.join(ARCHIVEDIR, folder), 'zip', os.path.join(LOGDIR, folder))

Dopo aver creato il file compresso nella nuova posizione, possiamo rimuovere la cartella originale e tutti i file in essa contenuti:

shutil.rmtree(os.path.join(LOGDIR, folder), ignore_errors=True)

A fine procedura, tutti i file esterni al periodo indicato sono stati inseriti in un archivio (uno per cartella) e spostati nella destinazione finale di archiviazione.

Ecco il codice completo dello script:

__author__ = 'Andrea Trivisonno'

import argparse
import os
import shutil
from datetime import datetime
from relativedelta import relativedelta

parser = argparse.ArgumentParser(description='Log rotate utility')
parser.add_argument(dest='logdir',metavar='logdir')
parser.add_argument(dest='archivedir',metavar='archivedir')
parser.add_argument(dest='monthsback',metavar='monthsback')
args = parser.parse_args()

LOGDIR = args.logdir
ARCHIVEDIR = args.archivedir
MONTHSBACK = -int(args.monthsback)
WARNING = 1
ERROR = 2
OK = 0

try:
    # check if log dir and archive dir exists
    if os.path.exists(LOGDIR) and os.path.exists(ARCHIVEDIR) :
        # create a date object based on how many months old the log archive should be
        log_rotate_datetime = datetime.today() + relativedelta(months=MONTHSBACK)
        # check if folder is older or not than log rotate date limit
        print "Archiving log created before %s " % log_rotate_datetime
        # list all folder in the log dir
        subdirectories = os.listdir(LOGDIR)
        # for each subdir splt name in year and month
        for folder in subdirectories:
            # create a date object based on folder date
            log_folder_datetime = datetime.strptime(folder, "%Y-%m")
            if log_folder_datetime < log_rotate_datetime :
                # ok we should archive and delete folder
                print "Compressing folder %s" % os.path.join(LOGDIR, folder)
                shutil.make_archive(os.path.join(ARCHIVEDIR, folder), 'zip', os.path.join(LOGDIR, folder))
                print "Created archive %s in folder %s " %(folder+".zip", ARCHIVEDIR)
                shutil.rmtree(os.path.join(LOGDIR, folder), ignore_errors=True)
                print "Removed folder %s" % os.path.join(LOGDIR, folder)
            else :
                # no we should ignore the log folder
                print "Ignoring folder %s " % os.path.join(LOGDIR, folder)
    else:
        print "Error, logdir o archivedir not found."
        exit(ERROR);
except Exception, e:
    print "some error occured: %s" % e
    exit(WARNING)
Annunci

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...