-
Notifications
You must be signed in to change notification settings - Fork 53
/
last_n_minutes
executable file
·56 lines (41 loc) · 2.31 KB
/
last_n_minutes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#!/bin/bash
# Print the last N minutes of standard linux log files
# By Todd Stein - May 12, 2014
minutes_to_look_back=$1
log_file=$2
if [[ ! -e "$log_file" || ! $minutes_to_look_back =~ ^[0-9]+$ ]]; then
echo "Usage: $0 <minutes> <log_file>" 1>&2
exit 1
fi
curr_month_num=$(date '+%m')
curr_month_year=$(date '+%Y')
if [[ $curr_month_num == "01" ]]; then # if this month is january
prev_month_num=12 # then last month was december
prev_month_year=$((curr_month_year-1)) # then last month's year was one less that this year
else
prev_month_num=$(printf "%02d\n" "$((${curr_month_num#0}-1))") # last month is one less
prev_month_year=$curr_month_year # last month's year is this year
fi
months=( ZERO Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ) # element zero exists to allow for easily lookup
curr_month_name="${months[${curr_month_num#0}]}" # expansion strips leading zero to allow for element lookup
prev_month_name="${months[${prev_month_num#0}]}" # expansion strips leading zero to allow for element lookup
time_string='(([0-9]| )[0-9]) ([0-9]{2}):([0-9]{2}):([0-9]{2}).+' # backreferences to "day hour min sec", match rest of line
curr_search_replace="s/^$curr_month_name $time_string/$curr_month_year $curr_month_num \1 \3 \4 \5/g"
prev_search_replace="s/^$prev_month_name $time_string/$prev_month_year $prev_month_num \1 \3 \4 \5/g"
## Print all lines of log_file newer than $minutes_to_look_back minutes old
#
# proposed_target = current seconds since epoch - how many seconds since epoch we want to prune to
# actual_target =
# tac - streams log_file backwards to sed
# | sed - reformats standard timestamp to 'YYYY MM DD HH MM SS' so awk can translate to seconds since epoch
# | awk - when the timestamp becomes older than our proposed target, print it (translated to seconds since epoch) + exit
# | date - translate timestamp (seconds since epoch) back to standard linux log format
proposed_target=$(echo "$(date +%s)-60*$minutes_to_look_back" | bc)
actual_target=$(
tac "$log_file" \
| sed -r "$curr_search_replace; $prev_search_replace" \
| awk -v t=$proposed_target '{if (mktime($0) < t) {print mktime($0); exit}}' \
| xargs -rI{} date -d '@{}' '+%b %e %H:%M:%S'
)
# stream log backwards printing all lines until target is reached, then re-invert output
tac $log_file | awk "/^$actual_target/ {exit}; {print}" | tac