asterisk/contrib/scripts/ast_loggrabber

256 lines
6.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Turn on extended globbing
shopt -s extglob
# Bail on any error
set -e
prog=$(basename $0)
print_help() {
cat <<EOF
NAME
$prog - Gather asterisk log files
SYNOPSIS
$prog [ --help ] [ --dateformat="<dateformat>" ]
[ --timezone="<timezone>" ] [ --append-logfiles ]
[ --tarball-uniqueid="<uniqueid>" ]
[ <logfiles> | <pattern> ... ]
DESCRIPTION
Gathers log files, optionally converts POSIX timestamps
to readable format. and creates a tarball.
Options:
--help
Print this help.
--dateformat="<dateformat>"
A Python strftime format string to be used when converting
POSIX timestamps in log files to readable format. If not
specified as an argument or in the config file, no conversion
is done.
--timezone="<timezone>"
The timezone to use when converting POSIX timestamps to
readable format. It can be specified in "<continent>/<city>"
format or in abbreviation format such as "CST6CDT". If not
specified as an argument or in the config file, the "local"
timezone is used.
--append-logfiles
Append any log files specified on the command line to the
config file specified ones instead of overriding them.
--tarball-uniqueid="<uniqueid>"
Normally DATEFORMAT is used to make the tarballs unique
but you can use your own unique id in the tarball names
such as a Jira issue id.
<logfiles> | <pattern>
A list of log files or log file search patterns. Unless
--append-logfiles was specified, these entries will override
those specified in the config files.
If no files are specified on the command line the, value of
LOGFILES from ast_debug_tools.conf will be used. Failing
that, the following patterns will be used:
/var/log/asterisk/messages*
/var/log/asterisk/queue*
/var/log/asterisk/debug*
/var/log/asterisk/security*
NOTES
Any files output will have ':' characters changed to '-'. This is
to facilitate uploading those files to Jira which doesn't like the
colons.
FILES
/etc/asterisk/ast_debug_tools.conf
~/ast_debug_tools.conf
./ast_debug_tools.conf
# Readable Local time for the tarball names
DATEFORMAT='date +%FT%H-%M-%S%z'
# A list of log files and/or log file search patterns using the
# same syntax as COREDUMPS.
#
LOGFILES=(/var/log/asterisk/messages* /var/log/asterisk/queue* \\
/var/log/asterisk/debug* /var/log/asterisk/security*)
# $prog converts POSIX timestamps to readable format
# using this Python strftime format string. If not specified
# or an empty string, no format covnersion is done.
LOG_DATEFORMAT="%m/%d %H:%M:%S.%f"
# The timezone to use when converting POSIX timestamps to
# readable format. It can be specified in "<continent>/<city>"
# format or in abbreviation format such as "CST6CDT". If not
# specified, the "local" timezone is used.
# LOG_TIMEZONE=
EOF
exit 1
}
append_logfiles=false
declare -a LOGFILES
declare -a ARGS_LOGFILES
# Read config files from least important to most important
[ -f /etc/asterisk/ast_debug_tools.conf ] && source /etc/asterisk/ast_debug_tools.conf
[ -f ~/ast_debug_tools.conf ] && source ~/ast_debug_tools.conf
[ -f ./ast_debug_tools.conf ] && source ./ast_debug_tools.conf
if [ ${#LOGFILES[@]} -eq 0 ] ; then
LOGFILES+=(/var/log/asterisk/messages* /var/log/asterisk/queue* \
/var/log/asterisk/debug* /var/log/asterisk/security*)
fi
DATEFORMAT=${DATEFORMAT:-'date +%FT%H-%M-%S%z'}
# Use "$@" (with the quotes) so spaces in patterns or
# file names are preserved.
# Later on when we have to iterate over LOGFILES, we always
# use the indexes rather than trying to expand the values of LOGFILES
# just in case.
for a in "$@" ; do
case "$a" in
--dateformat=*)
LOG_DATEFORMAT=${a#*=}
;;
--timezone=*)
LOG_TIMEZONE=${a#*=}
;;
--append-logfiles)
append_logfiles=true
;;
--tarball-uniqueid=*)
tarball_uniqueid=${a#*=}
;;
--help|-*)
print_help
;;
*)
ARGS_LOGFILES+=("$a")
# If any files are specified on the command line, ignore those
# specified in the config files unless append-logfiles was specified.
if ! $append_logfiles ; then
LOGFILES=()
fi
esac
done
# append logfiles/patterns specified as command line arguments to LOGFILES.
for i in ${!ARGS_LOGFILES[@]} ; do
LOGFILES+=("${ARGS_LOGFILES[$i]}")
done
# At this point, all glob entries that match files should be expanded.
# Any entries that don't exist are probably globs that didn't match anything
# and need to be pruned.
for i in ${!LOGFILES[@]} ; do
if [ ! -f "${LOGFILES[$i]}" ] ; then
unset LOGFILES[$i]
continue
fi
done
# Sort and weed out any dups
IFS=$'\x0a'
readarray -t LOGFILES < <(echo -n "${LOGFILES[*]}" | sort -u )
unset IFS
if [ "${#LOGFILES[@]}" -eq 0 ] ; then
echo "No log files found"
print_help
fi
# Timestamp to use for output files
df=${tarball_uniqueid:-$(${DATEFORMAT})}
# Extract the Python timestamp conver script from the end of this
# script and save it to /tmp/.ast_tsconvert.py
ss=`egrep -n "^#@@@SCRIPTSTART@@@" $0 |cut -f1 -d:`
tail -n +${ss} $0 >/tmp/.ast_tsconvert.py
tmpdir=$(mktemp -d)
if [ -z "$tmpdir" ] ; then
echo "${prog}: Unable to create temporary directory."
exit 1
fi
trap "rm -rf $tmpdir" EXIT
tardir=asterisk-${df}.logfiles
# Now iterate over the logfiles
for i in ${!LOGFILES[@]} ; do
lf=${LOGFILES[$i]}
destdir="$tmpdir/$tardir/$(dirname $lf)"
destfile="$tmpdir/$tardir/$lf"
mkdir -p "$destdir" 2>/dev/null || :
if [ -n "$LOG_DATEFORMAT" ] ; then
echo "Converting $lf"
cat "$lf" | python /tmp/.ast_tsconvert.py --format="$LOG_DATEFORMAT" --timezone="$LOG_TIMEZONE" > "${destfile}"
else
echo "Copying $lf"
cp "$lf" "${destfile}"
fi
done
echo "Creating /tmp/$tardir.tar.gz"
tar -czvf /tmp/$tardir.tar.gz -C $tmpdir $tardir 2>/dev/null
exit
# Be careful editing the inline scripts.
# They're space-indented.
# We need the python bit because lock_infos isn't
# a valid symbol in asterisk unless DEBUG_THREADS was
# used during the compile. Also, interrupt and continue
# are only valid for a running program.
#@@@SCRIPTSTART@@@
import argparse
import datetime as dt
import dateutil.tz as tz
import re
import sys
import time
parser = argparse.ArgumentParser(description="Make POSIX timestamps readable")
parser.add_argument('--format', action='store', required=True)
parser.add_argument('--timezone', action='store', required=False)
args=parser.parse_args()
# We only convert timestamps that are at the beginning of a line
# or are preceeded by a whitespace character or a '['
rets = re.compile(r'(^|(?<=\s|\[))\d+(\.\d+)?', flags=re.M)
if args.timezone and len(args.timezone) > 0:
tzf = tz.tzfile('/usr/share/zoneinfo/' + args.timezone)
else:
tzf = tz.tzfile('/etc/localtime')
now = time.time()
a_year_ago = now - (86400.0 * 365)
def convert(match):
ts = float(match.group(0))
if ts <= now and ts > a_year_ago and len(args.format) > 0:
return dt.datetime.fromtimestamp(ts, tzf).strftime(args.format)
else:
return match.group(0)
while 1:
line = sys.stdin.readline()
if not line:
break
print(rets.sub(convert, line))