我正在尝试设置一个 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
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 和双核处理器的机器上,shell 花费了大量时间来读取近 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 比它的bash
对手快了大约 65 倍。