LogRotate para Apache (on Windows) ;)


Opa!!!

Bom, criei este post para compartilhar um script que desenvolvi, para resolver um problema que eu venho tendo com alguns servidores rodando apache no Windows.

Os logs de acesso, erro etc, ficavam gigantes, e o apache ficava uma tartaruga. Arquivos com mais de 100 mb e o apache já agachava. Como não encontrei nada de “log rotate” para o Apache utilizando o Windows, resolvi fazer tal script parar resolver meu problema.

Depois de pronto, basta colocar no agendador de tarefas do Windows para executar diáriamente, ou conforme a sua demanda … Vamos por parte.  Primeiro vou explicar mais detalhadamente o problema ;)

Um servidor com Apache rodando no Windows. Seus arquivos de log chegaram a incrivelmente 20 GB. Com 300MB o apache já agacha… Portanto, o serviço tornou-se instável para não dizer que ele deixou de funcionar completamente.
O que eu precisava? Precisava de um serviço para fazer um logrotate como existe para Linux, porém, posso não ter procurado direito, mas não encontrei uma solução pronta para Windows.
Portanto, decidi fazer o script que é iniciado diáriamente pelo “Agendador de tarefas” do Windows, que vai lá na pastinha onde ficam os logs do Apache e verifica o tamanho dos arquivos de log. No meu caso, eu limitei a 10MB e está de bom tamanho pra mim 😉
Se encontrar arquivos de log que tenham mais de 10MB, ele para o serviço do Apache (o que é necessário pois enquanto o Apache funciona, os arquivos não podem ser editados), e compacta os arquivos encontrados em um arquivo “.tar.bz2” .
Depois de efetuar a compactação, ele apaga os arquivos “gigantes” e cria novos arquivos com o mesmo nome (necessários para o funcionamento do Apache) e inicia o serviço.

Bom, acho que o problema ficou bem explicado né 😉
Vale lembrar que estou falando de Apache, mas o trecho de código que utilizei para parar o serviço pode ser utilizado com qualquer serviço do Windows ok 😉

Então vamos lá… Vamos explicar as funções, e depois no fim do post, irei colocar o arquivo para download… Quem quiser me da R$ 10,00 obrigado porque as contas estão atrasadas 😉 – Brincadeira…

Primeiro os imports:

# -*- coding: utf-8 -*-
import os
import sys
import socket
import time
import datetime
import glob
import win32serviceutil
import tarfile
from stat import *

Agora, vamos as nossas variáveis:

tDate = datetime.datetime.now()
workDir = "C:\\Arquivos de programas\\Apache Group\\Apache2\\logs\\"
fileList = []
destinationfile = workDir + "BackupLogsApache-" + str(tDate.day) + "-" + str(tDate.month) + "-" + str(tDate.year) + ".tar.bz2"

MACHINE = socket.gethostname()
SERVICE = 'Apache2'

Explicando:
tDate, eu to pegando a data na hora que executo o scripts…
workDir é o diretório onde o script irá buscar pelos arquivos …
fileList é a lista onde serão adicionados os nomes dos arquivos maiores que 10MB
destinationfile é o nome do arquivo onde irei salvar os backups…
MACHINE é o nome do computador que está executando o script.
SERVICE é o serviço que iremos manipular 😉

Vamos agora a função que criamos para varrer o diretório:

def getFiles(workdir):
    for folder in glob.glob(workdir):
        for f in glob.glob(folder + "/*.log"):
            filesToRotate = getLogSize(f)
            print filesToRotate
        if filesToRotate:
            service_info('stop', MACHINE, SERVICE)
    compressFiles(filesToRotate, destinationfile)

Esta função busca pelos arquivos de log dentro da pasta especificada e chama a função “getLogSize(f)” passando o nome do arquivo como parâmetro para verificar o tamanho do mesmo. Se o arquivo for maior que 10MB, ele chama a função “service_info” com os parâmetros necessários para parar o serviço.
Depois chama a rotina de compressão dos arquivos…
Vamos ver a rotina de pegar o tamanho do arquivo :

def getLogSize(file_name):
    file_info = os.stat(file_name)
    tamanho = file_info[ST_SIZE]
    if tamanho > 10000:
        fileList.append(file_name)
        return fileList
    return fileList

Agora, a rotina para parar o serviço. O original pode ser encontrado aqui.

def service_info(action, machine, service):
    if action == 'stop':
        win32serviceutil.StopService(service, machine)
        print '%s stopped successfully' %service
    elif action == 'start':
        win32serviceutil.StartService(service) #find a bug in here... Already fixed 😉
        print '%s started successfully' %service
    elif action == 'restart':
        win32serviceutil.RestartService(service, machine)
        print '%s restarded successfully' %service
    elif action == 'status':
        if win32serviceutil.QueryServiceStatus(service, machine)[1] == 4:
            print '%s running normally' %service
        else:
            print '%s is NOT running' %service

Agora, a rotina para compactar os arquivos 😉

def compressFiles(file_list, destination_file):
    try:
        tar = tarfile.open(destination_file, "w:bz2")
        for f in file_list:
            tar.add(f, os.path.basename(f))
            os.remove(f)
            if createNewFile(os.path.basename(f)):
                print "Success !!! Rotation complete ;)"
       tar.close()
       service_info('start', MACHINE, SERVICE)
   except Exception, e:
       print "Ocorreu um erro - %s" %e

Explicando: Esta rotina compacta os arquivos encontrados, e após isto, remove os mesmo e chama a rotina para criar novamente os arquivos vazios. Depois, ela chama novamente a rotina que manipula os serviços para restartar o serviço especificado 😉
Vamos a rotina de criação do novo arquivo:

def createNewFile(file_name):
    try:
        fileHandle = open(workDir + file_name, "w")
        fileHandle.close
        return True
    except Exception, e:
        print e
        return False

Pronto! acabou nosso script.

Bom, futuramente, quero fazer umas verificações para confirmar se o serviço foi iniciado mesmo, e se não, ele disparar uma rotina que envia um e-mail avisando que não conseguiu iniciar o serviço.

Por enquanto é só! Sei que não sou ainda um computólogo, nem mesmo um super pythonista, portanto, várias rotinas e funções podem e devem ser melhoradas.

Para o que eu preciso, já está me atendendo 😉

Qualquer dúvida pergunta aí… Ops… O arquivo né… Segue o link abaixo 😉

Dependências:

pywin32

LINK

Abraços!

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: