Поиск диапазона дат

Я изучаю попытку установить сценарий Bash, который позволил бы мне вводить диапазон дат, подтверждать диапазон и затем на самом деле искать упомянутый диапазон. Но каждый раз, когда я пробую, это, кажется, просто подходит пустое по некоторым причинам. Я следовал за логикой, базирующейся ЗДЕСЬ, который немного стар, но надо надеяться имел некоторые точные части к ней. Я знаю, что код груб, и может быть очищен, но я являюсь все еще довольно новым в этом, и любая справка очень ценилась бы.

#!/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")
-1
задан 23 May 2017 в 05:39

1 ответ

1. Лучшее решение: Python

Используя bash поскольку задача, такая как это могла бы быть немного слишком сложной, потому что она не имеет достаточных инструментов с этой целью. Конечно, это может быть сделано, но с очень большим усилием. Поэтому нам нужен набор инструментов, которые могут позволить нам анализировать файл журнала более простым способом. Python предлагает такой набор инструментов через datetime модуль.

Сценарий Python представил ниже взятий 3 аргумента на командной строке: единственный - или дважды - заключенная в кавычки начинающаяся метка времени, единственная - или дважды - заключенная в кавычки конечная метка времени, и файл для чтения. Формат меток времени должен согласовываться с 'днем в понедельник формат 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

Тестовый прогон на /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

Конечно, это возможно, делают к так в bash, с использованием date и awk утилиты для извлечения меток времени и преобразований. Ниже bash реализация того же сценария 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. Сравнение двух подходов

Естественно, bash версия занимает намного более длительное время. Shell не сделан для обработки большого объема данных, такого как журналы. Например, на моей машине с SSD и двухъядерном процессоре, оболочка заняла существенное количество времени для чтения почти 13 000 файлов строки:

$ 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

Даже несколько оптимизации с if операторы не помогли. Сравните это с, он - альтернатива 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

Как Вы видите, Python был приблизительно в 65 раз быстрее, чем bash дубликат.

3
ответ дан 7 November 2019 в 01:03

Другие вопросы по тегам:

Похожие вопросы: