пятница, 4 мая 2012 г.

Ротация логов

Клевый скрипт. И он работает! Особенности:
1) ротация проходит по интервалу в днях,
2) в названии файлов используется год-месяц-день, то есть ротация по имени, а не по времени создания файла (хотя и это сделать можно)
3) для каждой папки надо создавать 3 записи в settings.ini: откуда, куда и маска файлов
4) в settings.ini используются названия fromN toN maskN, где N число
Вобщем вот пример settings.ini

[local]
logfile = Rotation.log

[copy]
dayinterval = 11
count = 3

from1 = D:\Router_xxx_xx_x_x\abonent\
to1 = K:\Router_xxx_xx_x_x\abonent\
mask1 = NF_%Y_%m_%d

from2 = D:\Router_xxx_xx_x_x\authorize\
to2 = K:\Router_xxx_xx_x_x\authorize\
mask2 = NF_%Y_%m_%d

from3 = D:\NAS_xxx-xx-xx-xx\
to3 = K:\NAS_xxx-xx-xx-xxx\
mask3 = %Y-%m-%d


В скрипте маленькая функция, которая архивирует файлики

### Archive and remove
def arch (filename, archivename, isrm):
        if not os.path.exists (os.path.dirname (archivename)):
                os.makedirs (os.path.dirname (archivename))
        try:
                os.chdir (os.path.dirname (archivename))
                fout = gzip.open (os.path.basename(archivename), 'wb')
        except IOError:
                print ('Error creating archive file')
                return
        fin = open (filename, 'rb')                                
        fout.writelines (fin)
        fout.close()
        fin.close()
        if isrm:
                os.remove (filename)


А вот сам скрипт

###   MAIN        
if __name__ == '__main__':
        import gzip
        import configparser
        import time
        import re
        import os
        from datetime import date
        from datetime import timedelta

        cfg = configparser.RawConfigParser()
        cfg.read ('settings.ini')
        logfile = open (cfg.get ('local', 'logfile'), 'a')
        logfile.writelines (time.strftime 
        ("\n[%Y-%m-%d %H:%M:%S] ") +'Service starts')
        dayinterval = cfg.get ('copy', 'dayinterval')
        date_from = date.today() - timedelta (days=int(dayinterval))
        cnt = cfg.get ('copy', 'count')
        i = 1
        while i <= int(cnt) :
                dir_from = cfg.get ('copy', 'from'+str(i))
                dir_to = cfg.get ('copy', 'to'+str(i))+
                date_from.strftime ("%Y-%m\\")
                filemask = cfg.get ('copy', 'mask'+str(i))
                datemask = date_from.strftime (filemask)
                mask = re.compile (datemask, re.IGNORECASE)
                flist = filter (mask.search, os.listdir(dir_from))
                for f in flist:
                        logfile.writelines (time.strftime 
                        ("\n[%Y-%m-%d %H:%M:%S] ") + dir_from+f)
                        arch (dir_from+f, dir_to+f+'.gz',True)
                i = i + 1
        logfile.writelines (time.strftime 
        ("\n[%Y-%m-%d %H:%M:%S] ") +'Service ends')
        logfile.close()



UPD: приделал раскладывание файлов по месяцам.

9 комментариев:

  1. 1) Ты уж определись os.makedirs или makedirectory.

    2) if isrm == 1: для таких ситуаций есть True/False

    3)
    i = 1
    while i <= int(cnt) :
    Это неплохо бы заменить на for с инициализацией, чтобы не пропустить инкремент
    for x in range(1, cnt + 1):

    4) А вот это самое суровое:
    try:
    fout = gzip.open(archivename, 'wb')
    except:
    os.makedirs(os.path.dirname(archivename))

    Ты бы хоть ловил IOError, а ещё лучше просто делал проверку на существование
    if os.path.exists(os.path.dirname(archivename)):
    fout = gzip.open(archivename, 'wb')

    а то ты так любое исключение ловишь и создаёшь директорию, а там ведь может вылететь всё что угодно.

    ОтветитьУдалить
  2. 1) ну ты тут меня уже разок головой макнул, я понял теперь :)
    2) да, чет я затупил
    3) те же яйца, хотя с эстетической стороны может быть ты и прав
    4) ну да, ну да, я пишу как быдло. я просто не запоминаю названия эксепшенов. не могу себя к этому приучить. надо было бить в детстве.

    ОтветитьУдалить
  3. >> ну да, ну да, я пишу как быдло.
    >> я просто не запоминаю названия эксепшенов.
    >> не могу себя к этому приучить.
    >> надо было бить в детстве.

    Ну от того, что ты пишешь "я пишу как быдло", я мимо нехорошего кода молча не пройду. Да и пишу я тут не для того, чтобы ты так писал. Исправляйся, Саша, - жить легче будет.

    ОтветитьУдалить
  4. Чтоб не забыть: ты сказал, что перепишешь этот адский код, особенно этот кусок

    try:
    fout = gzip.open (archivename, 'wb')
    except:
    os.makedirs (os.path.dirname (archivename))

    ОтветитьУдалить
  5. все, переписал.
    сейчас обновлю пост. Заодно затру плохой код, чтоб не позориться

    ОтветитьУдалить
  6. Зачем ты ловишь исключение, если ничего не делаешь с ним? Я бы переписал вот так (ведущие подчёркивания замени на пробелы):

    def arch(filename, archivename, isrm):
    ____archive_dir = os.path.dirname(archivename)
    ____if not os.path.exists(archive_dir):
    ________os.makedirs(archive_dir)

    ____with open(filename, 'rb') as fin, open(archivename, 'wb') as fout:
    ________fout.writelines(fin)

    ____if isrm:
    ________os.remove(filename)

    ОтветитьУдалить
  7. нельзя делать open(archivename, 'wb') as fout
    потому что:
    1) не open, а gzip.open
    2) если ты не хочешь, чтоб у тебя в архиве не было полной структуры каталогов исходного файла надо сначала перейти в папку, где будет архив и только потом паковать, то есть:
    os.chdir (os.path.dirname (archivename))
    fout = gzip.open (os.path.basename(archivename), 'wb')

    ОтветитьУдалить
  8. def arch(filename, archivename, isrm):
    ____archive_dir = os.path.dirname(archivename)
    ____if not os.path.exists(archive_dir):
    ________os.makedirs(archive_dir)
    ____os.chdir(archive_dir)

    ____with open(filename, 'rb') as fin, gzip.open((os.path.basename(archivename), 'wb') as fout:
    ________fout.writelines(fin)

    ____if isrm:
    ________os.remove(filename)

    ОтветитьУдалить
  9. Одна скобка лишняя, вот так лучше:

    with open(filename, 'rb') as fin, gzip.open(os.path.basename(archivename), 'wb') as fout:

    ОтветитьУдалить