Criando um script bash para logrotation com data em foldername

1

Eu tenho uma estrutura de pastas em / var / log assim:

.
├── customers
│   ├── core00001
│   │   ├── 2016.07.21
│   │   │   ├── apache.log
│   │   │   └── error.log
│   │   └── 2016.07.22
│   │       ├── apache.log
│   │       └── error.log
│   ├── core00002
│   │   ├── 2016.07.21
│   │   │   ├── apache.log
│   │   │   └── error.log
│   │   └── 2016.07.22
│   │       ├── apache.log
│   │       └── error.log
│   ├── dashboard001
│   │   ├── 2016.07.21
│   │   │   ├── dash.log
│   │   │   └── error.log
│   │   └── 2016.07.22
│   │       ├── dash.log
│   │       └── error.log
│   └── dashboard002
│       ├── 2016.07.21
│       │   ├── dash.log
│       │   └── error.log
│       └── 2016.07.22
│           ├── dash.log
│           └── error.log
└── servers
    ├── server01
    │   ├── 2016.07.21
    │   │   ├── access.log
    │   │   └── system.log
    │   └── 2016.07.22
    │       ├── access.log
    │       └── system.log
    └── server02
        ├── 2016.07.21
        │   ├── access.log
        │   └── system.log
        └── 2016.07.22
            ├── access.log
            └── system.log

Com essas pastas, preciso fazer algum tipo de rotação de log. Não é uma rotação de log real, mas preciso zipar e excluir arquivos após um determinado período de dias. Pensei em fazer um arquivo de configuração no qual eu possa colocar a quantidade de dias após um arquivo precisar ser zipado e a quantidade de dias após um arquivo e a pasta vazia precisar ser excluída.

Os núcleos e servidores podem aumentar e os nomes dos arquivos de log podem ser adicionados a cada servidor. Por esse motivo, pensei em usar um arquivo de configuração com o script bash, para poder adicionar nomes aqui.

Minha primeira ideia do arquivo de configuração é assim:

Zip;Delete;Main;Sub;App

7;365;/customers;core*;/apache.log
7;365;/customers;core*;/error.log

7;180;/customers;dash*;/dash.log
7;180;/customers;dash*;/error.log

28;365;/servers;server*;/access.log
14;365;/servers;server*;/error.log

Meu problema é que não sei como conseguir isso sem ajuda.

Eu já tentei criar um loop onde o arquivo de configuração será lido, mas apenas uma linha será lida e o script será interrompido.

#!/bin/bash
configfile="/etc/customlogrotate/logrotation.conf"
logbasefolder="/var/log"

echo " " > log.txt
echo " " >> log.txt
echo "Starting logrotation script" >> log.txt

while IFS=';' read -r daysafterzip daystosave sectionfolder logfilename
do
echo "$daysafterzip $daystosave $logbasefolder$sectionfolder$logfilename" >> log.txt

cd $logbasefolder

done < "$configfile"

Editar: Obrigado pelas respostas. Eu finalmente consegui trabalhar com a variável $ logfile.

Eu agora uso este script (sem a variável logfile, porque tudo funciona por enquanto):

#!/bin/bash
# This file is managed by Ansible - Contact SysAdmin for changes!!
# file: roles/syslog-ng/templates/logrotation.sh.j2

configfile="/etc/customlogrotate/logrotation.conf"
logbasefolder="/var/log"

# Move to logbasefolder
cd $logbasefolder

# Loop all options from the configfile
while IFS=';' read -r daystozip daystodelete sectionfolder subsectionfolder logfilename
do

        datetozip='date -d "$daystozip days ago" +%Y%m%d'
        datetodelete='date -d "$daystodelete days ago" +%Y%m%d'

        cd $logbasefolder$sectionfolder

        for hostfolder in $subsectionfolder/
        do
                cd $hostfolder

                # loop trough all date folder in hostfolder
                for datefolder in [0-9][0-9][0-9][0-9].[0-9][0-9].[0-9][0-9]
                do
                        # remove dashes from datefolder
                        datefoldershort='echo "$datefolder" | tr -d .'

                        # check if logfile is to be deleted based on date
                        if test "$datefoldershort" -lt "$datetodelete"
                        then
                                cd $datefolder

                                # search folder for logfilename and delete it
                                for filetodelete in $logfilename.gz
                                do
                                        #Put script for deletion here    
                                done

                                # move back one folder to continue the list
                                cd ..

                        # check if logfile is to be zipped based on date
                        elif test "$datefoldershort" -lt "$datetozip"
                        then
                                cd $datefolder
                                # search folder for logfilename and zip it
                                for filetozip in $logfilename
                                do
                                        gzip ${logfilename:1}
                                done
                               # move back one folder to continue the list
                                cd ..
                        fi
                done

                # move back one folder to continue the list
                cd ..
        done
done < "$configfile"

Com este arquivo de configuração:

11;14;/customers;core*;/apache.log
10;13;/customers;core*;/custom.log
9;12;/customers;core*;/system.log
11;14;/customers;srv*;/error.log
8;9;/customers;srv*;/system.log

Obrigado novamente !!

    
por Marco Sysadmin 26.07.2016 / 11:50

2 respostas

0

O script está funcionando conforme o esperado, mas altera o diretório em que ele escreve log.txt .

Inicialmente, o script grava em log.txt no diretório atual, mas o script altera seu diretório. O comando cd $logbasefolder altera o diretório atual para que o script comece a escrever log.txt em um diretório, mas depois do comando cd , ele escreve log.txt to $logbasefolder .

Corrija o problema usando uma variável para o caminho gravável para log.txt ( $PWD ou $HOME são possibilidades) ou use pushd e popd para trocar diretórios entre o diretório inicial e $logbasefolder . Por exemplo:

#!/bin/bash
configfile="/etc/customlogrotate/logrotation.conf"
logbasefolder="/var/log"
logfile="$PWD/log.txt"

echo " " > $logfile
echo " " >> $logfile
echo "Starting logrotation script" >> $logfile

while IFS=';' read -r daysafterzip daystosave sectionfolder logfilename
do

echo "$daysafterzip $daystosave $logbasefolder$sectionfolder$logfilename" >> $logfile

# alternative method to $logfile variable:
# pushd $logbasefolder > /dev/null
#  zip and delete files ...
# popd > /dev/null
cd $logbasefolder   # remove with pushd and popd

done < "$configfile"
    
por 26.07.2016 / 13:37
0

Eu acho que você pode ter que fazer isso de forma um pouco diferente (mas eu posso estar errado). Pelo que posso dizer, você pode precisar de algo que você pode automatizar (ou seja, usar algo como crontab). Isso significa:

  • , você escreve um script que percorre todas as pastas abaixo de "/ var / log /", lê o nome de cada arquivo, verifica o agendamento de arquivamento desse tipo de arquivo e verifica quando esse arquivo específico foi arquivado por último e proceda de acordo;
  • ou, você torna sua vida um pouco mais fácil criando vários scripts dedicados a uma finalidade específica e configurando cronjobs para cada um deles.

Pessoalmente, eu prefiro a segunda opção. É muito mais modular e, depois de implementado, provavelmente também é mais fácil de manter. A coisa toda seria então algo parecido com isto:

  • Script1: compactar todos os clientes / * / * log; setar o cron para rodar isso a cada 7 dias
  • Script2: compactar todos os servidores / * / access.log; definir o cron para ser executado a cada 28 dias
  • Script3: compactar todos os servidores / * / error.log; cron a cada 14 dias
  • Script4: exclua todos os arquivos que precisam ser excluídos após 365 dias; definir o cron adequadamente
  • Script5: exclua todos os arquivos que precisam ser excluídos após 180 dias; definir o cron adequadamente

Parece mais entediante e complicado do que deveria ser na verdade, é modular, fácil de manter e ajustar.

Espero que isso ajude. JW

    
por 26.07.2016 / 12:14