Я изучаю попытку установить сценарий 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")
Используя 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
Конечно, это возможно, делают к так в 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 "$@"
Естественно, 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
дубликат.