87dd74faf0
Debian and Centos use the same tools but they are installed in different places. In order for collect to work on Debian, make sure that we are trying not use to RPMs on Debian. This is done in the collect-patching script so that the "smart" program is not run. Also kdump uses the /var/lib/kdump path on Debian rather than /var/crash on Centos. Also checked for 'rpm -qa' usage and changed them to 'dpkg -l'. Test Plan PASS Build package PASS Build and install ISO PASS Run the collect -v -all Story: 2009101 Task: 43732 Depends-On: https://review.opendev.org/c/starlingx/tools/+/838327 Signed-off-by: Charles Short <charles.short@windriver.com> Change-Id: I66cf0615f8cab7fe877b6cb09d605557c9258c43
1065 lines
37 KiB
Bash
Executable File
1065 lines
37 KiB
Bash
Executable File
#!/bin/bash
|
|
#######################################################################
|
|
#
|
|
# Copyright (c) 2017 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
########################################################################
|
|
#
|
|
# This file is a new member of the Titanium Cloud "Log Collect Utility".
|
|
# This file enhances date restricted collect in response.
|
|
#
|
|
# This file is invoked by collect_host when a date restricted
|
|
# collect using --start-date and/or --end-date options are used.
|
|
#
|
|
# This new data restricted collect service applies to /var/log and its
|
|
# subdirectories only. This service determines if a log file is to be
|
|
# included in dated collect by looking at the logs at the head and tail
|
|
# of the files and subdirectories in /var/log. Those dates are then
|
|
# compared to the user specified date range. if a file is determined to
|
|
# contain logs within that date range then that file is included in the
|
|
# collect log. A valid log date prefix is "YYYY-MM-DD".
|
|
#
|
|
# Unfortunately, not all log files contain the correct date placement and
|
|
# format. This feature has implemented special case handling for many but not
|
|
# not all of such cases. To avoid accidental exclusion of a key file, this
|
|
# feature will by default include log files whose log date content could
|
|
# not be determined if its file date is after the specified start date.
|
|
#
|
|
# Note: local convension , example ${head_date} vs ${HEAD_DATE}
|
|
#
|
|
# Lower case date variables contain integer values while
|
|
# Upper case date variables contain formatted string values of same.
|
|
#
|
|
# Calling sequence:
|
|
#
|
|
# /usr/local/sbin/collect_date <start_date> <end_date> <include_list> <debug>
|
|
# /usr/local/sbin/collect_date 20170701 20170901 /tmp/file.list true
|
|
#
|
|
########################################################################
|
|
|
|
#
|
|
# Import commands, variables and convenience functions available to
|
|
# all collectors ; common and user defined.
|
|
#
|
|
source /usr/local/sbin/collect_utils
|
|
|
|
# where to find the logs
|
|
declare -r baselogdir="/var/log"
|
|
|
|
# include / exclude labels
|
|
declare -r INCLUDE_FILE="inc"
|
|
declare -r EXCLUDE_FILE="exc"
|
|
|
|
# a global reason string that is only valid
|
|
# in the context of the file beeing looked at.
|
|
declare __this_reason=""
|
|
|
|
# setup defaults
|
|
INC_FILE_LIST="/var/run/collect_include.list"
|
|
EXC_FILE_LIST="/var/run/collect_exclude.list"
|
|
NOD_FILE_LIST="/var/run/collect_nodate.list"
|
|
|
|
BOT_DATE="2000-01-01" # beginning of time date
|
|
bot_date=730013 # beginning of time date as integer
|
|
|
|
EOT_DATE="9999-12-31" # end of time date
|
|
eot_date=3649810 # end of time date as integer
|
|
|
|
# manage debug mode
|
|
DEBUG="${4}"
|
|
set_debug_mode "${DEBUG}"
|
|
echo "Debug Mode: ${DEBUG}"
|
|
|
|
dlog "collect_date args: ${1} ${2} ${3} ${4} ${5}"
|
|
|
|
#############################################################################
|
|
#
|
|
# 'track' is the main accounting procedure that manages file inclusions and
|
|
# exclusions as well as the metrics around all the parsed files.
|
|
#
|
|
# It also reports accounting mismatch logs, if they occur (should not)
|
|
# and the file that started the mismatch (to assist in debug).
|
|
#
|
|
# $1 - filename
|
|
# $2 - label
|
|
#
|
|
#############################################################################
|
|
|
|
# accounting defaults
|
|
declare -i file_count=0
|
|
declare -i inc_file_count=0
|
|
declare -i exc_file_count=0
|
|
declare -i empty_file_count=0
|
|
|
|
function track()
|
|
{
|
|
local fn="${1}"
|
|
local label="${2}"
|
|
|
|
if [ -z "${fn}" ] ; then
|
|
elog "Ignoring call with empty filename"
|
|
return
|
|
|
|
elif [ "${label}" == "totals" ] ; then
|
|
((file_count++))
|
|
return
|
|
|
|
elif [ "${label}" == "empty" ] ; then
|
|
((empty_file_count++))
|
|
return
|
|
|
|
elif [ "${label}" == "${INCLUDE_FILE}" ] ; then
|
|
manage_file "${fn}" "${label}" "${__this_reason}"
|
|
((inc_file_count++))
|
|
|
|
elif [ "${label}" == "${EXCLUDE_FILE}" ] ; then
|
|
manage_file "${fn}" "${label}" "${__this_reason}"
|
|
((exc_file_count++))
|
|
|
|
else
|
|
elog "Unknown label '${label}'"
|
|
|
|
fi
|
|
|
|
sum=$((inc_file_count + exc_file_count))
|
|
if [ ${file_count} -ne ${sum} ] ; then
|
|
wlog "MISMATCH: ${file_count} != ${inc_file_count} + ${exc_file_count} - ${fn}"
|
|
fi
|
|
}
|
|
|
|
############################################################################
|
|
#
|
|
# 'summary' is an accounting display procedure used to show the
|
|
# accounting results of the total number of files processed,
|
|
# number of empty files and most importanly the number if
|
|
# included or excluded files.
|
|
#
|
|
############################################################################
|
|
|
|
function summary()
|
|
{
|
|
dlog "Summary:"
|
|
dlog "Total Files: ${file_count}"
|
|
dlog "Empty Files: ${empty_file_count}"
|
|
dlog "Added Files: ${inc_file_count}"
|
|
dlog "Omitd Files: ${exc_file_count}"
|
|
}
|
|
|
|
#############################################################################
|
|
#
|
|
# 'date_to_int' converts a standard formatted YYYY-MM-DD string date
|
|
# to an integer and stores it in __this_integer_date variable
|
|
# to be used in context on demand.
|
|
#
|
|
#############################################################################
|
|
|
|
# short lived global integer date value updated by date_to_int utility
|
|
declare -i __this_integer_date=""
|
|
|
|
function date_to_int()
|
|
{
|
|
local yy="${1:0:4}"
|
|
local mm="${1:5:2}"
|
|
local dd="${1:8:2}"
|
|
|
|
# handle leading zeros in month and day
|
|
if [ "${mm:0:1}" == "0" ] ; then
|
|
mm=${mm:1:1}
|
|
fi
|
|
if [ "${dd:0:1}" == "0" ] ; then
|
|
dd=${dd:1:1}
|
|
fi
|
|
|
|
# 365 days in a year, 31 days in a month, 1 day in a day
|
|
__this_integer_date=$((yy*365 + mm*31 + dd))
|
|
}
|
|
|
|
############################################################################
|
|
#
|
|
# 'create_list_file' removes old/stale list file and creates a new empty
|
|
# one with correct permissions.
|
|
#
|
|
############################################################################
|
|
|
|
function create_list_file()
|
|
{
|
|
local fn="${1}"
|
|
if [ -e "${fn}" ] ; then
|
|
rm -f "${fn}"
|
|
fi
|
|
touch "${fn}"
|
|
chmod 644 "${fn}"
|
|
}
|
|
|
|
########################################################################
|
|
#
|
|
# Handle the incoming 'start' and 'end' date format defensively.
|
|
#
|
|
# If the date is with no dashes as it would come in from the user's
|
|
# date specification then set it up like the standard date delimited with '-'
|
|
# i.e. 20171002 is updated to 2017-10-02.
|
|
#
|
|
# If verified to be in the standard format just copy in.
|
|
#
|
|
# Otherwise assume the start date is from the beginning of time or
|
|
# end date is the end of time.
|
|
|
|
# load up the start date string and integer representation
|
|
if [ -z "${1}" ] ; then
|
|
START_DATE="${BOT_DATE}"
|
|
elif [[ "${1}" =~ [0-9]{4}[0-9]{2}[0-9]{2} ]] ; then
|
|
START_DATE="${1:0:4}-${1:4:2}-${1:6:2}"
|
|
elif [[ "${1}" =~ [0-9]{4}-[0-9]{2}-[0-9]{2} ]] ; then
|
|
START_DATE="${1}"
|
|
else
|
|
START_DATE="${BOT_DATE}"
|
|
fi
|
|
|
|
# Convert the correct or corrected 'start' date to an integer value
|
|
date_to_int "${START_DATE}"
|
|
start_date=${__this_integer_date}
|
|
|
|
|
|
# load up the end date string and integer representation
|
|
if [ -z "${2}" ] ; then
|
|
END_DATE="${EOT_DATE}"
|
|
elif [[ "${2}" =~ [0-9]{4}[0-9]{2}[0-9]{2} ]] ; then
|
|
END_DATE="${2:0:4}-${2:4:2}-${2:6:2}"
|
|
elif [[ "${2}" =~ [0-9]{4}-[0-9]{2}-[0-9]{2} ]] ; then
|
|
END_DATE="${2}"
|
|
else
|
|
END_DATE="${EOT_DATE}"
|
|
fi
|
|
|
|
# Convert the correct or corrected 'end' date to an integer value
|
|
date_to_int "${END_DATE}"
|
|
end_date=${__this_integer_date}
|
|
|
|
# Handle user error of specifying an end date that is before the start date
|
|
if [ ${start_date} -gt ${end_date} ] ; then
|
|
wlog "invalid date range ; end date (${END_DATE}:${end_date}) is before start (${START_DATE}:${start_date})"
|
|
wlog "correcting to defaults: from ${START_DATE} to ${END_DATE}"
|
|
START_DATE="${BOT_DATE}"
|
|
END_DATE="${EOT_DATE}"
|
|
start_date=${bot_date}
|
|
end_date="${eot_date}"
|
|
fi
|
|
|
|
ilog "collecting log files containing logs dated ${START_DATE} to ${END_DATE} (inclusive)"
|
|
|
|
|
|
if [ "${3}" == "" ] ; then
|
|
elog "dated collect include file list name not specified ... exiting"
|
|
exit 1
|
|
else
|
|
VAR_LOG_INCLUDE_LIST=${3}
|
|
fi
|
|
|
|
create_list_file "${VAR_LOG_INCLUDE_LIST}"
|
|
create_list_file "${INC_FILE_LIST}"
|
|
create_list_file "${EXC_FILE_LIST}"
|
|
create_list_file "${NOD_FILE_LIST}"
|
|
|
|
# Declare and init the include and exclude debug lists.
|
|
inclist=("")
|
|
exclist=("")
|
|
|
|
#############################################################################
|
|
#
|
|
# 'filedatelist' is a list of files that are known to not contain dated logs.
|
|
# Instead these files are included unless its file date is
|
|
# older that the specified start date.
|
|
#
|
|
#############################################################################
|
|
|
|
filedatelist=("")
|
|
filedatelist+=("/var/log/wtmp")
|
|
filedatelist+=("/var/log/dmesg")
|
|
filedatelist+=("/var/log/dmesg.old")
|
|
filedatelist+=("/var/log/sm-trap.log")
|
|
filedatelist+=("/var/log/sm-customer.log")
|
|
filedatelist+=("/var/log/sm-customer.alarm")
|
|
filedatelist+=("/var/log/sm-shutdown.log")
|
|
filedatelist+=("/var/log/nfv-vim-events.log")
|
|
filedatelist+=("/var/log/fm-customer.log")
|
|
filedatelist+=("/var/log/fm-alarm.log")
|
|
filedatelist+=("/var/log/lighttpd-access.log")
|
|
filedatelist+=("/var/log/audit/audit.log")
|
|
filedatelist+=("/var/log/rabbitmq/shutdown_log")
|
|
filedatelist+=("/var/log/rabbitmq/startup_log")
|
|
filedatelist+=("/var/log/rabbitmq/wait_log")
|
|
filedatelist+=("/var/log/rabbitmq/rabbit@localhost.log")
|
|
filedatelist+=("/var/log/nfv-vim-alarms.log")
|
|
filedatelist+=("/var/log/vswitch.cmds.log")
|
|
|
|
# This is a list of files to always include
|
|
autoaddlist=("")
|
|
autoaddlist+=("/var/log/collect.log")
|
|
|
|
#########################################################################
|
|
#
|
|
# 'is_in_range' returns true if the specified log file data range
|
|
# is within the bounded date range specified by the caller.
|
|
# Otherwise a false is returned.
|
|
#
|
|
# ${1} is HEAD_DATE and is the date of the first log of the file in contect
|
|
# ${2} is TAIL_DATE and is the date of the last log in the file in context
|
|
#
|
|
# expected date format is ... YYYY-MM-DD
|
|
#
|
|
# Calling Sequence is ... is_in_range HEAD_DATE TAIL_DATE
|
|
#
|
|
# There are several cases that aer handled ;
|
|
# see case comment inline below.
|
|
#
|
|
#########################################################################
|
|
|
|
function is_in_range()
|
|
{
|
|
local HEAD_DATE="${1}"
|
|
local TAIL_DATE="${2}"
|
|
if [[ ${HEAD_DATE} =~ [0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
|
|
|
|
# Convert the date to an integer value
|
|
# to make the compare easier and faster
|
|
date_to_int "${HEAD_DATE}"
|
|
head_date=${__this_integer_date}
|
|
|
|
if [[ ${TAIL_DATE} =~ [0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
|
|
|
|
# Convert the date to an integer value
|
|
# to make the compare easier and faster
|
|
date_to_int "${TAIL_DATE}"
|
|
tail_date=${__this_integer_date}
|
|
|
|
in_range=false
|
|
|
|
# The last log is before the start date or the first log is after the end date
|
|
# if [[ "${TAIL_DATE}" < "${START_DATE}" || "${HEAD_DATE}" > "${END_DATE}" ]] ; then
|
|
if [ ${tail_date} -lt ${start_date} -o ${head_date} -gt ${end_date} ] ; then
|
|
__this_reason+=":case 0"
|
|
in_range=false
|
|
|
|
# Case 1: the head after the start but before the end date
|
|
# .... S ... head ... E ....
|
|
elif [ ${head_date} -ge ${start_date} -a ${head_date} -le ${end_date} ] ; then
|
|
__this_reason+=":case 1"
|
|
in_range=true
|
|
|
|
# Case 2: the tail after the start but before the end date
|
|
# .... S ... tail ... E ....
|
|
elif [ ${tail_date} -ge ${start_date} -a ${tail_date} -le ${end_date} ] ; then
|
|
__this_reason+=":case 2"
|
|
in_range=true
|
|
|
|
# Case 3: log file date range spans the start and end dates
|
|
# head S ... ... E tail
|
|
elif [ ${head_date} -le ${start_date} -a ${tail_date} -ge ${end_date} ] ; then
|
|
__this_reason+=":case 3"
|
|
in_range=true
|
|
|
|
else
|
|
__this_reason+=":default"
|
|
fi
|
|
else
|
|
__this_reason+=":invalid-tail-date"
|
|
# so the tail date is unknown.
|
|
# include this file as long as the head date is before end date
|
|
if [ ${head_date} -lt ${end_date} ] ; then
|
|
in_range=true
|
|
else
|
|
in_range=false
|
|
fi
|
|
fi
|
|
|
|
if [ "${in_range}" = true ] ; then
|
|
__this_reason+=":in-range ${HEAD_DATE} to ${TAIL_DATE}"
|
|
true
|
|
else
|
|
__this_reason+=":out-of-range ${HEAD_DATE} to ${TAIL_DATE}"
|
|
false
|
|
fi
|
|
return
|
|
fi
|
|
|
|
__this_reason+=":date-format-error ${HEAD_DATE} to ${TAIL_DATE}"
|
|
true
|
|
return
|
|
}
|
|
|
|
###########################################################################
|
|
#
|
|
# Name : want_this_file
|
|
#
|
|
# Description: This utility first compares the filename to known exception
|
|
# cases and handles them accordingly. Exception cases do look
|
|
# for the date but with different methods. Once the date info
|
|
# is or is not found then the choice to or not to include it
|
|
# follows same general logic as others below.
|
|
#
|
|
# If not an exception case then it determines the file type
|
|
# and performs any preprocessing required. i.e. uncompressing
|
|
# the file and switching the filename to the uncompressed name.
|
|
# Data files or other unknown file types are automatically
|
|
# included without further data query by immediately returning
|
|
# true.
|
|
#
|
|
# With an expected supported filename in hand this utility will
|
|
# extract the date-only (time not included) portion, the first
|
|
# 10 characters of the first and last logs and determin if this
|
|
# logfile has logs that fall withing the specified date range.
|
|
#
|
|
# Returns : If there is no valid date found then true is returned.
|
|
# If file contains in range logs then true is returned.
|
|
# if file does not contain in range logs then false is returned.
|
|
#
|
|
# Parameters : $1 is the full pathed log file name.
|
|
#
|
|
# $1 - the filename of the file to check the date for
|
|
#
|
|
###########################################################################
|
|
|
|
function want_this_file()
|
|
{
|
|
local inc=true
|
|
local LOGFILE="${1}"
|
|
local filetype=$(file "${LOGFILE}")
|
|
local HEAD_DATE=""
|
|
local TAIL_DATE=""
|
|
|
|
for add in "${autoaddlist[@]}"
|
|
do
|
|
if [ "${add}" == "${LOGFILE}" ] ; then
|
|
__this_reason+="autoadd"
|
|
true
|
|
return
|
|
fi
|
|
done
|
|
|
|
##########################################################################
|
|
# Exception Case: known free formatted log files.
|
|
##########################################################################
|
|
#
|
|
# Some log files are known to not contain properly dated logs.
|
|
# Such files may just contian free format strings of information.
|
|
#
|
|
# A list of such files is in hard coded in filedatelist.
|
|
# TODO: consider making this a file that is loaded.
|
|
#
|
|
# Check to see if this is an auto add file
|
|
# Only exlude such files if its last modified date is before start date.
|
|
#
|
|
##########################################################################
|
|
for add in "${filedatelist[@]}"
|
|
do
|
|
if [ "${add}" == "${LOGFILE}" ] ; then
|
|
__this_reason+="filedate"
|
|
|
|
# Don't include empty files that are in the hard coded filedatelist
|
|
filetype=$(file "${LOGFILE}")
|
|
if [ ! -z "${filetype}" ] ; then
|
|
case ${filetype} in
|
|
*empty*)
|
|
__this_reason="empty"
|
|
track "${LOGFILE}" "empty"
|
|
false
|
|
return
|
|
;;
|
|
*)
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# get last modified date
|
|
FILE_DATE=$(stat -c %y "${LOGFILE}" | cut -b 1-10)
|
|
date_to_int "${FILE_DATE}"
|
|
if [ ${__this_integer_date} -ge ${start_date} ] ; then
|
|
__this_reason+=":in-range ${FILE_DATE}"
|
|
true
|
|
else
|
|
__this_reason+=":out-of-range ${FILE_DATE}"
|
|
false
|
|
fi
|
|
return
|
|
fi
|
|
done
|
|
|
|
# O.K. if we get here then this filename is not in the static list
|
|
if [ ! -z "${filetype}" ] ; then
|
|
|
|
case ${filetype} in
|
|
|
|
*directory*)
|
|
# Skip over a directory only path.
|
|
# No worries, the files in that directory will be handled.
|
|
__this_reason+="directory"
|
|
false
|
|
return
|
|
;;
|
|
|
|
*ASCII*|*text*|*compressed*)
|
|
|
|
if [[ ${filetype} == *"compressed"* ]] ; then
|
|
fileext=${LOGFILE##*.}
|
|
case "${fileext}" in
|
|
gz)
|
|
tmpfile=$(mktemp)
|
|
#__this_reason+="gzipped"
|
|
zcat "${LOGFILE}" | head -5 > "$tmpfile"
|
|
zcat "${LOGFILE}" | tail -5 >> "$tmpfile"
|
|
|
|
# save the current compressed log filename
|
|
# so that it can be restored after the
|
|
# recursion call below
|
|
LOGFILE_save="${LOGFILE}"
|
|
want_this_file "$tmpfile"
|
|
rc=${?}
|
|
LOGFILE="${LOGFILE_save}"
|
|
|
|
# cleanup ; get rid of the temp file
|
|
rm -f "$tmpfile" 2>/dev/null
|
|
if [ ${rc} -eq 0 ] ; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
return
|
|
;;
|
|
tgz)
|
|
__this_reason+="tarball"
|
|
true
|
|
return
|
|
;;
|
|
*)
|
|
__this_reason+="compress:[${fileext}]"
|
|
true
|
|
return
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# Read the first log in the file
|
|
HEAD_DATE=$(head -1 "${LOGFILE}")
|
|
|
|
##############################################################
|
|
# Minor Exception Case: empty/short first log
|
|
##############################################################
|
|
#
|
|
# handle one empty or short first line by fetching second log
|
|
#
|
|
##############################################################
|
|
|
|
if [ ${#HEAD_DATE} -lt 10 ] ; then
|
|
HEAD_DATE=$(head -2 "${LOGFILE}" | sed -n '2p' | cut -b 1-11)
|
|
fi
|
|
|
|
|
|
##############################################################
|
|
# Typical Case: YYYY-MM-DD
|
|
##############################################################
|
|
#
|
|
# check for most typical date format.
|
|
#
|
|
##############################################################
|
|
|
|
if [[ ${HEAD_DATE} =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
|
|
__this_reason+="typical"
|
|
TAIL_DATE=$(tail -1 "${LOGFILE}" | cut -b 1-11)
|
|
if [[ ${TAIL_DATE} =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
|
|
|
|
# a call to 'is_in_range' returns false (1) if this
|
|
# file's logs are all out of range date
|
|
is_in_range "${HEAD_DATE:0:10}" "${TAIL_DATE:0:10}"
|
|
if [ $? -eq 0 ] ; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
return
|
|
|
|
else
|
|
|
|
#######################################################
|
|
# Exception Case: Unrecognized date format in last log
|
|
#######################################################
|
|
#
|
|
# try the second last line. This case is typical in
|
|
# cron.log in 15.12 MAIL logs which send a purious ')'
|
|
# as a second log. Also if the log file has auto blank
|
|
# lines between logs leaving a blank line as the last
|
|
# log.
|
|
#
|
|
# this exception ties the second last log instead.
|
|
#
|
|
#######################################################
|
|
TAIL_DATE=$(tail -2 "${LOGFILE}" | sed -n '1p' | cut -b 1-11)
|
|
if [[ ${TAIL_DATE} =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
|
|
|
|
is_in_range "${HEAD_DATE:0:10}" "${TAIL_DATE:0:10}"
|
|
if [ $? -eq 0 ] ; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
return
|
|
|
|
else
|
|
# default to true if the dates could not be parsed
|
|
__this_reason+=":invalid-tail-date"
|
|
|
|
date_to_int "${HEAD_DATE}"
|
|
head_date=${__this_integer_date}
|
|
|
|
# so the tail date is unknown.
|
|
# include this file as long as the head date is before end date
|
|
if [ ${head_date} -lt ${end_date} ] ; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
return
|
|
fi
|
|
fi
|
|
|
|
else
|
|
|
|
###########################################################
|
|
# Exception Case 1: logs date prefix starts with '['
|
|
###########################################################
|
|
#
|
|
# logdate starts with a '[' ... [2017-10-02
|
|
#
|
|
# In this case we just recognize it and increment past it
|
|
# and then assume the last log will have the same format
|
|
#
|
|
###########################################################
|
|
|
|
if [ "${HEAD_DATE:0:1}" == "[" ] ; then
|
|
__this_reason+="exception1"
|
|
HEAD_DATE=${HEAD_DATE:1:11}
|
|
if [[ ${HEAD_DATE} =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
|
|
|
|
TAIL_DATE=$(tail -1 "${LOGFILE}" | cut -b 2-11)
|
|
if [[ ${TAIL_DATE} =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
|
|
__this_reason+=".1"
|
|
is_in_range "${HEAD_DATE:0:10}" "${TAIL_DATE:0:10}"
|
|
if [ $? -eq 0 ] ; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
return
|
|
else
|
|
TAIL_DATE=$(tail -1 "${LOGFILE}" | cut -b 1-10)
|
|
if [[ ${TAIL_DATE} =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
|
|
__this_reason+=".2"
|
|
is_in_range "${HEAD_DATE:0:10}" "${TAIL_DATE:0:10}"
|
|
if [ $? -eq 0 ] ; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
return
|
|
|
|
else
|
|
|
|
if [ "${TAIL_DATE:0:1}" == "[" ] ; then
|
|
__this_reason+=".3"
|
|
TAIL_DATE=${TAIL_DATE:1:11}
|
|
if [[ ${TAIL_DATE} =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
|
|
is_in_range "${HEAD_DATE}" "${TAIL_DATE}"
|
|
if [ $? -eq 0 ] ; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
return
|
|
else
|
|
__this_reason+=":invalid-tail-date"
|
|
true
|
|
return
|
|
fi
|
|
else
|
|
__this_reason+=":tail-date-not-found"
|
|
is_in_range "${HEAD_DATE}" "${EOT_DATE}"
|
|
if [ $? -eq 0 ] ; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
return
|
|
fi
|
|
fi
|
|
fi
|
|
else
|
|
# /var/log/dmesg is typical of this case
|
|
# no log date and many logs start with [ uptime]
|
|
__this_reason+=":invalid-head-date"
|
|
true
|
|
return
|
|
fi
|
|
|
|
###########################################################
|
|
# Exception Case 2: journel.log handling
|
|
###########################################################
|
|
#
|
|
# first log in file contains start and stop date
|
|
#
|
|
# "-- Logs begin at Thu 2017-07-06 12:28:35 UTC, end at Thu 2017-07-06 12:33:31 UTC. --"
|
|
# ^^^^^^^^^^ ^^^^^^^^^^
|
|
#
|
|
# This exception case gets the head and tail log date from
|
|
# this first log.
|
|
###########################################################
|
|
|
|
elif [ "${HEAD_DATE:0:13}" == "-- Logs begin" ] ; then
|
|
__this_reason+="exception2"
|
|
|
|
# need to get more of the line
|
|
HEAD_DATE=$(head -1 "${LOGFILE}")
|
|
|
|
is_in_range "${HEAD_DATE:21:10}" "${HEAD_DATE:57:10}"
|
|
if [ $? -eq 0 ] ; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
return
|
|
|
|
###########################################################
|
|
# Exception Case 3: journel.log handling
|
|
###########################################################
|
|
#
|
|
# some logs like openstack.log have some logs that are
|
|
# prefixed by keystone:log. This case handles that
|
|
#
|
|
###########################################################
|
|
elif [ "${HEAD_DATE:0:13}" == "keystone:log " ] ; then
|
|
__this_reason+="exception3"
|
|
|
|
# need to get more of the line
|
|
HEAD_DATE="${HEAD_DATE:13:10}"
|
|
TAIL_DATE=$(tail -1 "${LOGFILE}")
|
|
|
|
if [ "${TAIL_DATE:0:13}" == "keystone:log " ] ; then
|
|
TAIL_DATE="${TAIL_DATE:13:10}"
|
|
else
|
|
TAIL_DATE="${TAIL_DATE:0:10}"
|
|
fi
|
|
|
|
is_in_range "${HEAD_DATE}" "${TAIL_DATE}"
|
|
if [ $? -eq 0 ] ; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
return
|
|
|
|
else
|
|
|
|
#######################################################
|
|
# Exception Case 4: horizon.log
|
|
#######################################################
|
|
#
|
|
# Search the first and last 30 logs for a valid date.
|
|
# This should handle seeing a traceback at the head or
|
|
# tail of the log file.
|
|
#
|
|
#######################################################
|
|
__this_reason+="exception4"
|
|
temp_head=$(head -30 "${LOGFILE}")
|
|
for ((loop_head=1;loop_head<31;loop_head++))
|
|
do
|
|
HEAD_DATE=$(echo "${temp_head}" | sed -n "${loop_head}"p | cut -b 1-10)
|
|
if [[ ${HEAD_DATE} =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
|
|
temp_tail=$(tail -30 "${LOGFILE}")
|
|
for ((loop_tail=1;loop_tail<31;loop_tail++))
|
|
do
|
|
TAIL_DATE=$(echo "${temp_tail}" | sed -n ${loop_tail}p | cut -b 1-10)
|
|
if [[ ${TAIL_DATE} =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then
|
|
|
|
is_in_range "${HEAD_DATE}" "${TAIL_DATE}"
|
|
if [ $? -eq 0 ] ; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
return
|
|
|
|
fi
|
|
done
|
|
|
|
# default to including it if no date at
|
|
# the end of the file is found
|
|
true
|
|
return
|
|
fi
|
|
done
|
|
|
|
######################################################
|
|
# Exception Case 5:
|
|
######################################################
|
|
#
|
|
# Otherwise the file has no date or the date
|
|
# format is unrecognized so just include the file
|
|
# regardless of its date.
|
|
#
|
|
######################################################
|
|
__this_reason="nodate"
|
|
true
|
|
return
|
|
fi
|
|
fi
|
|
;;
|
|
|
|
*archive*)
|
|
|
|
# Archive files like .tar are not extracted.
|
|
# Instead it is only collected if its last modified date is
|
|
# after the start date
|
|
|
|
__this_reason+="archive"
|
|
FILE_DATE=$(stat -c %y "${LOGFILE}" | cut -b 1-10)
|
|
date_to_int "${FILE_DATE}"
|
|
if [ ${__this_integer_date} -ge ${start_date} ] ; then
|
|
__this_reason+=":in-range ${FILE_DATE}"
|
|
true
|
|
else
|
|
__this_reason+=":out-of-range ${FILE_DATE}"
|
|
false
|
|
fi
|
|
return
|
|
;;
|
|
|
|
*empty*)
|
|
__this_reason="empty"
|
|
track "${LOGFILE}" "empty"
|
|
false
|
|
return
|
|
;;
|
|
|
|
*data*)
|
|
__this_reason="data"
|
|
true
|
|
return
|
|
;;
|
|
|
|
*executable*)
|
|
__this_reason="executable"
|
|
true
|
|
return
|
|
;;
|
|
|
|
# very short file (no magic)
|
|
*"very short file"*)
|
|
__this_reason="small"
|
|
true
|
|
return
|
|
;;
|
|
|
|
*link*)
|
|
__this_reason="link"
|
|
false
|
|
return
|
|
;;
|
|
|
|
*swap*)
|
|
|
|
__this_reason="swap"
|
|
false
|
|
return
|
|
;;
|
|
|
|
*fifo*)
|
|
|
|
__this_reason="fifo"
|
|
false
|
|
return
|
|
;;
|
|
|
|
*socket*)
|
|
|
|
__this_reason="socket"
|
|
false
|
|
return
|
|
;;
|
|
|
|
*)
|
|
__this_reason="other"
|
|
true
|
|
return
|
|
;;
|
|
esac
|
|
else
|
|
__this_reason="unknown"
|
|
wlog "Adding ${logfile} ; unknown filetype"
|
|
true
|
|
return
|
|
fi
|
|
|
|
# catch all default
|
|
true
|
|
return
|
|
}
|
|
|
|
#############################################################################
|
|
#
|
|
# 'manage_file' adds the specified file to either the 'include' or exclude'
|
|
# reason lists. In the include case the most important part of
|
|
# this function appends the filename to the file specified by
|
|
# "VAR_LOG_INCLUDE_LIST" which is the file that collect_host
|
|
# uses to know what files in /var/log need to be included in
|
|
# the collect tarball.
|
|
#
|
|
#############################################################################
|
|
|
|
function manage_file()
|
|
{
|
|
local filename="${1}"
|
|
local action="${2}"
|
|
local reason="${3}"
|
|
|
|
if [ "${action}" == "${EXCLUDE_FILE}" ] ; then
|
|
echo "${filename} excluded (${reason})" >> "${EXC_FILE_LIST}"
|
|
else
|
|
echo "${filename} included (${reason})" >> "${INC_FILE_LIST}"
|
|
|
|
# add the file to the list of files to be collected
|
|
echo "${filename}" >> ${VAR_LOG_INCLUDE_LIST}
|
|
fi
|
|
|
|
dlog "${action}: ${filename} (${reason})"
|
|
}
|
|
|
|
#############################################################################
|
|
#
|
|
# 'handle_response' adds or excludes the specified file based on
|
|
# arguement $2 being 0 - true - include or
|
|
# !0 - false - exclude
|
|
#
|
|
# $1 - file
|
|
# $2 - include control ( true or false )
|
|
#
|
|
#############################################################################
|
|
|
|
function handle_response()
|
|
{
|
|
local logfile="${1}"
|
|
local include="${2}"
|
|
|
|
if [ "${include}" -eq 0 ] ; then
|
|
inclist=("${inclist[@]}" ${logfile})
|
|
track "${logfile}" "${INCLUDE_FILE}"
|
|
|
|
else
|
|
exclist=("${exclist[@]}" ${logfile})
|
|
track "${logfile}" "${EXCLUDE_FILE}"
|
|
fi
|
|
|
|
# record any that have been tagged as 'nodate' as
|
|
# candidate for special handling.
|
|
if [[ "${__this_reason}" == *"nodate"* ]] ; then
|
|
echo "${logfile}" >> "${NOD_FILE_LIST}"
|
|
fi
|
|
}
|
|
|
|
###########################################################################
|
|
###########################################################################
|
|
#
|
|
# Lets start looking at the files now ...
|
|
#
|
|
# Get all the files in /var/log base dir (not the subdirectories)
|
|
#
|
|
###########################################################################
|
|
###########################################################################
|
|
|
|
# get a list of the files in "baselogdir" ; aka /var/log
|
|
# will look at the sub directories later.
|
|
dirlist+=$(find ${baselogdir} -mindepth 1 -maxdepth 1 -type f)
|
|
|
|
#
|
|
# Debug:
|
|
#
|
|
# To debug handling a specific file as a filelist override.
|
|
# This clears the list in favor of the specific file specified as
|
|
# argument 8 on the command line.
|
|
#
|
|
if [ "${5}" != "" ] ; then
|
|
dlog "Overriding dirlist with specified file:${5}"
|
|
dirlist=("${5}")
|
|
fi
|
|
|
|
# echo "${baselogdir} filelist: ... ${dirlist}..."
|
|
for logfile in ${dirlist}
|
|
do
|
|
# echo "File: ${logfile}"
|
|
__this_reason=""
|
|
track "${logfile}" "totals"
|
|
want_this_file "${logfile}"
|
|
handle_response "${logfile}" "${?}"
|
|
done
|
|
|
|
###########################################################################
|
|
# Get all the files in baselogdir subdirectories #
|
|
###########################################################################
|
|
|
|
subdirlist=$(find ${baselogdir} -mindepth 1 -maxdepth 20 -type d)
|
|
|
|
#
|
|
# Debug:
|
|
#
|
|
# To debug handling a specific file that is in a /var/log subdirectory as a
|
|
# filelist override.
|
|
#
|
|
if [ "${5}" != "" ] ; then
|
|
dlog "Overriding subdirlist with specified file:${5}"
|
|
subdirlist=("")
|
|
fi
|
|
|
|
# echo "${baselogdir} subdirlist ${subdirlist}..."
|
|
for logdir in ${subdirlist}
|
|
do
|
|
__this_reason=""
|
|
|
|
# this find must find more than just its own dir
|
|
# so we compare to greater than one
|
|
if [ $(find "${logdir}" | wc -l) -gt 1 ]; then
|
|
for logfile in ${logdir}/*
|
|
do
|
|
__this_reason=""
|
|
track "$logfile" "totals"
|
|
want_this_file "$logfile"
|
|
handle_response "$logfile" "$?"
|
|
done
|
|
else
|
|
__this_reason="empty"
|
|
manage_file "${logdir}" "${EXCLUDE_FILE}" "empty directory"
|
|
fi
|
|
done
|
|
|
|
|
|
dlog "Include List: ${INC_FILE_LIST}"
|
|
for inc in "${inclist[@]}"
|
|
do
|
|
if [ ${#inc} -gt 2 ] ; then
|
|
dlog "including ${inc}"
|
|
# echo "${inc}" >> "${INC_FILE_LIST}.summary"
|
|
fi
|
|
done
|
|
|
|
|
|
dlog "Exclude List: ${EXC_FILE_LIST}"
|
|
for exc in "${exclist[@]}"
|
|
do
|
|
if [ ${#exc} -gt 2 ] ; then
|
|
dlog "excluding ${exc}"
|
|
# echo "${exc}" >> "${EXC_FILE_LIST}.summary"
|
|
fi
|
|
done
|
|
|
|
summary
|
|
|
|
exit 0
|