Procurando pelo intervalo de datas

-1

Estou tentando configurar um script BASH que permita inserir um intervalo de datas, confirmar o intervalo e pesquisar o intervalo. Mas toda vez que eu tento, parece que fica vazio por algum motivo. Eu estava seguindo a lógica baseada AQUI que é um pouco antiga , mas espero que tenha algumas partes precisas para isso. Eu sei que o código é áspero e pode ser limpo, mas eu ainda sou bastante novo nisso e qualquer ajuda seria muito apreciada.

#!/bin/bash

date_1=''
date_2=''

read -p "Please Enter the Beggining Time. Exp. Aug 1 00:00:01 " date_1;

read -p "Please Enter the Beggining Time. Exp. Aug 1 00:00:01 " date_2;

while :
 do
    read -p "Is this Date correct? @date_1" choice
    case ${choice} in
        y|ye|yes) break;;
        n|no) echo "Try again"; exec $0;;
    esac
done
while :
 do
    read -p "Is this Date correct? @date_2" choice
    case ${choice} in
        y|ye|yes) break;;
        n|no) echo "Try again"; exec $0;;
    esac
done

echo $date_1 , $date_2
find /srv/log/mail -mtime $(date +%s -d"$date_1") -mtime $(date +%s -d"$date_2")
    
por Temple Pate 06.02.2017 / 00:27

1 resposta

3

1. Melhor solução: Python

Usar bash para tarefas como essas pode ser um pouco complexo demais, porque não possui ferramentas suficientes para essa finalidade. Certamente isso pode ser feito, mas com muito esforço. Portanto, precisamos de um conjunto de ferramentas que nos permita analisar o arquivo de log de maneira mais simples. O Python oferece esse conjunto de ferramentas via datetime module.

O script python apresentado a seguir leva 3 argumentos na linha de comando: registro de data e hora de início com aspas simples ou dupla, registro de data e hora de finalização com aspas simples ou dupla e o arquivo a ser lido. O formato dos timestamps deve ser consistente com o formato 'Mon day HH: MM: SS'.

#!/usr/bin/env python
import datetime as dt
import sys

def convert_to_seconds(timestring):
    year = str(dt.date.today().year)
    dtobj = dt.datetime.strptime( year + ' ' + timestring , '%Y %b %d %H:%M:%S' )
    return int(dtobj.strftime('%s'))

beginning = convert_to_seconds(sys.argv[1])
ending = convert_to_seconds(sys.argv[2])

with open(sys.argv[3]) as log:
    for line in log:
        logstamp = " ".join(line.strip().split()[0:3])
        s_logstamp = convert_to_seconds(logstamp)
        if s_logstamp < beginning: continue
        if s_logstamp >= beginning and s_logstamp <= ending:
            print(line.strip())
            sys.stdout.flush()
        if s_logstamp > ending: break

Teste executado em /var/log/syslog :

$ ./read_log_range.py 'Feb 8 13:57:00'  'Feb 8 14:00:00' /var/log/syslog                              
Feb  8 13:57:59 eagle gnome-session[28631]: (nm-applet:28825): GdkPixbuf-CRITICAL **: gdk_pixbuf_composite: assertion 'dest_x >= 0 && dest_x + dest_width <= dest->width' failed
Feb  8 13:59:55 eagle org.gtk.vfs.Daemon[28480]: ** (process:2259): WARNING **: Couldn't create directory monitor on smb://x-gnome-default-workgroup/. Error: Operation not supported by backend
Feb  8 13:59:59 eagle gnome-session[28631]: (nm-applet:28825): GdkPixbuf-CRITICAL **: gdk_pixbuf_composite: assertion 'dest_x >= 0 && dest_x + dest_width <= dest->width' failed

2. Bash

Naturalmente, é possível fazer isso em bash , com o uso dos utilitários date e awk para extrair os registros de data e hora e as conversões. Abaixo está a implementação bash do mesmo script python.

#!/usr/bin/env bash
#set -x
str_to_seconds(){
    date -d"$1" +%s
}

main(){
    local date1=$1
    local date2=$2
    local logfile=$3

    local s_date1=$(str_to_seconds "$date1")
    local s_date2=$(str_to_seconds "$date2")

    while IFS= read -r line;
    do
        timestamp=$(awk '{print $1,$2,$3}' <<< "$line")
        s_timestamp=$(str_to_seconds "$timestamp")
        [ $s_timestamp -lt $s_date1  ] && continue
        if [ $s_timestamp -ge $s_date1  ] && [ $s_timestamp -le $s_date2  ]
        then
            printf "%s\n" "$line"
        fi
        [ $s_timestamp -gt $s_date2  ] && break

    done < "$logfile"
}

main "$@"

3. Comparação das duas abordagens

Naturalmente, a versão bash demora muito mais tempo. O shell não é feito para processamento de grande quantidade de dados, como logs. Por exemplo, na minha máquina com SSD e processador dual core, o shell demorou um tempo significativo para ler quase 13.000 arquivos de linha:

$ time ./read_log_range.sh 'Feb 8 13:56:00'  'Feb 8 14:00:00' '/var/log/syslog' &> /dev/null          
    0m39.18s real     0m02.48s user     0m02.68s system

$ wc -l /var/log/syslog 
12878 /var/log/syslog

Até mesmo várias otimizações com instruções if não ajudaram. Compare isso com sua alternativa em python:

$ time ./read_log_range.py 'Feb 8 13:56:00'  'Feb 8 14:00:00' '/var/log/syslog' &> /dev/null          
    0m00.60s real     0m00.53s user     0m00.07s system

$ wc -l /var/log/syslog                                                                               
12878 /var/log/syslog

Como você pode ver, o Python foi cerca de 65 vezes mais rápido que sua contraparte bash .

    
por Sergiy Kolodyazhnyy 06.02.2017 / 01:46