@ -15,7 +15,7 @@ SYNOPSIS
$prog [ --help ] [ --running | --RUNNING ] [ --latest ]
$prog [ --help ] [ --running | --RUNNING ] [ --latest ]
[ --tarball-coredumps ] [ --delete-coredumps-after ]
[ --tarball-coredumps ] [ --delete-coredumps-after ]
[ --tarball-results ] [ --delete-results-after ]
[ --tarball-results ] [ --delete-results-after ]
[ --tarball-uniqueid="<uniqueid>" ]
[ --tarball-config ] [ --tarball- uniqueid="<uniqueid>" ]
[ --no-default-search ] [ --append-coredumps ]
[ --no-default-search ] [ --append-coredumps ]
[ --asterisk-bin="path" ]
[ --asterisk-bin="path" ]
[ <coredump> | <pattern> ... ]
[ <coredump> | <pattern> ... ]
@ -51,7 +51,8 @@ DESCRIPTION
Create a coredump from the running asterisk instance and
Create a coredump from the running asterisk instance and
process it along with any other coredumps found (if any).
process it along with any other coredumps found (if any).
WARNING: This WILL interrupt call processing. You will be
WARNING: This WILL interrupt call processing. You will be
asked to confirm.
asked to confirm. The coredump will be written to /tmp if
$OUTPUTDIR is not defined.
--RUNNING
--RUNNING
Same as --running but without the confirmation prompt.
Same as --running but without the confirmation prompt.
@ -69,10 +70,11 @@ DESCRIPTION
/usr/sbin/asterisk, /usr/lib(64)/libasterisk* and
/usr/sbin/asterisk, /usr/lib(64)/libasterisk* and
/usr/lib(64)/asterisk as those files are needed to properly
/usr/lib(64)/asterisk as those files are needed to properly
examine the coredump. The file will be named
examine the coredump. The file will be named
/tmp /asterisk.<timestamp>.coredumps.tar.gz or
$OUTPUTDIR /asterisk.<timestamp>.coredumps.tar.gz or
/tmp /asterisk-<uniqueid>.coredumps.tar.gz if
$OUTPUTDIR /asterisk-<uniqueid>.coredumps.tar.gz if
--tarball-uniqueid was specified.
--tarball-uniqueid was specified.
WARNING: This file could 1gb in size!
WARNING: This file could 1gb in size!
Mutually exclusive with --tartball-results
--delete-coredumps-after
--delete-coredumps-after
Deletes all processed coredumps regardless of whether
Deletes all processed coredumps regardless of whether
@ -81,7 +83,8 @@ DESCRIPTION
--tarball-results
--tarball-results
Creates a gzipped tarball of all result files produced.
Creates a gzipped tarball of all result files produced.
The tarball name will be:
The tarball name will be:
/tmp/asterisk.<timestamp>.results.tar.gz
$OUTPUTDIR/asterisk.<timestamp>.results.tar.gz
Mutually exclusive with --tartball-coredumps
--delete-results-after
--delete-results-after
Deletes all processed results regardless of whether
Deletes all processed results regardless of whether
@ -89,6 +92,10 @@ DESCRIPTION
to use this option unless you have also specified
to use this option unless you have also specified
--tarball-results.
--tarball-results.
--tarball-config
Adds the contents of /etc/asterisk to the tarball created
with --tarball-coredumps or --tarball-results.
--tarball-uniqueid="<uniqueid>"
--tarball-uniqueid="<uniqueid>"
Normally DATEFORMAT is used to make the tarballs unique
Normally DATEFORMAT is used to make the tarballs unique
but you can use your own unique id in the tarball names
but you can use your own unique id in the tarball names
@ -130,6 +137,10 @@ DESCRIPTION
NOTES
NOTES
You must be root to use $prog.
You must be root to use $prog.
$OUTPUTDIR can be read from the current environment or from the
ast_debug_tools.conf file described below. If not specified,
work products are placed in the same directory as the core file.
The script relies on not only bash, but also recent GNU date and
The script relies on not only bash, but also recent GNU date and
gdb with python support. *BSD operating systems may require
gdb with python support. *BSD operating systems may require
installation of the 'coreutils' and 'devel/gdb' packagess and minor
installation of the 'coreutils' and 'devel/gdb' packagess and minor
@ -166,6 +177,12 @@ FILES
# anyway.
# anyway.
COREDUMPS=(/tmp/core[-._]asterisk!(*.txt) /tmp/core[-._]\$(hostname)!(*.txt))
COREDUMPS=(/tmp/core[-._]asterisk!(*.txt) /tmp/core[-._]\$(hostname)!(*.txt))
# The directory to contain output files and work directories.
# For output from existing core files, the default is the
# directory that the core file is found in. For core files
# produced from a running process, the default is /tmp.
OUTPUTDIR=/some/directory
# Date command for the "running" coredump and tarballs.
# Date command for the "running" coredump and tarballs.
# DATEFORMAT will be executed to get the timestamp.
# DATEFORMAT will be executed to get the timestamp.
# Don't put quotes around the format string or they'll be
# Don't put quotes around the format string or they'll be
@ -227,6 +244,13 @@ if [ -z "$GDB" ] ; then
exit 1
exit 1
fi
fi
if [ -n "$OUTPUTDIR" ] ; then
if [ ! -d "$OUTPUTDIR" ] ; then
echo "OUTPUTDIR $OUTPUTDIR doesn't exists or is not a directory"
exit 1
fi
fi
if [ ${#COREDUMPS[@]} -eq 0 ] ; then
if [ ${#COREDUMPS[@]} -eq 0 ] ; then
COREDUMPS+=(/tmp/core[-._]asterisk!(*.txt) /tmp/core[-._]$(hostname)!(*.txt))
COREDUMPS+=(/tmp/core[-._]asterisk!(*.txt) /tmp/core[-._]$(hostname)!(*.txt))
fi
fi
@ -326,6 +350,10 @@ fi
# Timestamp to use for output files
# Timestamp to use for output files
df=${tarball_uniqueid:-$(${DATEFORMAT})}
df=${tarball_uniqueid:-$(${DATEFORMAT})}
if [ -z "$asterisk_bin" ]; then
asterisk_bin=$(which asterisk)
fi
if $running || $RUNNING ; then
if $running || $RUNNING ; then
# We need to go through some gyrations to find the pid of the running
# We need to go through some gyrations to find the pid of the running
# MAIN asterisk process and not someone or something running asterisk -r.
# MAIN asterisk process and not someone or something running asterisk -r.
@ -351,9 +379,9 @@ if $running || $RUNNING ; then
read -p "WARNING: Taking a core dump of the running asterisk instance will suspend call processing while the dump is saved. Do you wish to continue? (y/N) " answer
read -p "WARNING: Taking a core dump of the running asterisk instance will suspend call processing while the dump is saved. Do you wish to continue? (y/N) " answer
fi
fi
if [[ "$answer" =~ ^[Yy] ]] ; then
if [[ "$answer" =~ ^[Yy] ]] ; then
cf="/tmp/core-asterisk-running-$df"
cf="${OUTPUTDIR:- /tmp} /core-asterisk-running-$df"
echo "Dumping running asterisk process to $cf"
echo "Dumping running asterisk process to $cf"
${GDB} -p $pid -q --batch --ex "gcore $cf" >/dev/null 2>&1
${GDB} ${asterisk_bin} -p $pid -q --batch --ex "gcore $cf" >/dev/null 2>&1
COREDUMPS+=("$cf")
COREDUMPS+=("$cf")
else
else
echo "Skipping dump of running process"
echo "Skipping dump of running process"
@ -370,20 +398,22 @@ fi
# and save them to /tmp/.gdbinit
# and save them to /tmp/.gdbinit
ss=`egrep -n "^#@@@SCRIPTSTART@@@" $0 |cut -f1 -d:`
ss=`egrep -n "^#@@@SCRIPTSTART@@@" $0 |cut -f1 -d:`
tail -n +${ss} $0 >/tmp/.ast_coredumper.gdbinit
tail -n +${ss} $0 >${OUTPUTDIR:- /tmp} /.ast_coredumper.gdbinit
# Now iterate over the coredumps and dump the debugging info
# Now iterate over the coredumps and dump the debugging info
for i in ${!COREDUMPS[@]} ; do
for i in ${!COREDUMPS[@]} ; do
cf=${COREDUMPS[$i]}
cf=${COREDUMPS[$i]}
echo "Processing $cf"
echo "Processing $cf"
if [ -z "$asterisk_bin" ]; then
asterisk_bin=$(which asterisk)
cfdir=`dirname ${cf}`
fi
cfname=`basename ${cf}`
${GDB} -n --batch -q --ex "source /tmp/.ast_coredumper.gdbinit" "$asterisk_bin" "$cf" 2>/dev/null | (
outputdir=${OUTPUTDIR:-${cfdir}}
${GDB} -n --batch -q --ex "source ${OUTPUTDIR:-/tmp}/.ast_coredumper.gdbinit" "$asterisk_bin" "$cf" 2>/dev/null | (
of=/dev/null
of=/dev/null
while IFS= read line ; do
while IFS= read line ; do
if [[ "$line" =~ !@!@!@!\ ([^\ ]+)\ !@!@!@! ]] ; then
if [[ "$line" =~ !@!@!@!\ ([^\ ]+)\ !@!@!@! ]] ; then
of=${cf}-${BASH_REMATCH[1]}
of=${outputdir}/${ cfname }-${BASH_REMATCH[1]}
of=${of//:/-}
of=${of//:/-}
rm -f "$of"
rm -f "$of"
echo "Creating $of"
echo "Creating $of"
@ -391,50 +421,58 @@ for i in ${!COREDUMPS[@]} ; do
echo -e $"$line" >> "$of"
echo -e $"$line" >> "$of"
done
done
)
)
done
if $tarball_coredumps ; then
if $tarball_coredumps ; then
tf=/tmp/asterisk-$df.coredumps.tar.gz
cfname=${cfname//:/-}
echo "Creating $tf"
tf=${outputdir}/${cfname}.tar.gz
dest=/tmp/asterisk-$df
echo "Creating ${tf}"
rm -rf $dest 2>/dev/null || :
libdir=usr/lib
[ -d /usr/lib64 ] && libdir+=64
mkdir -p $dest/tmp $dest/$libdir/asterisk $dest/etc $dest/usr/sbin
for i in ${!COREDUMPS[@]} ; do
ln -s "${COREDUMPS[@]}" $dest/"${COREDUMPS[@]}"
cp "${COREDUMPS[@]}"*.txt $dest/tmp/
done
cp /etc/os-release $dest/etc/
cp -a /$libdir/libasterisk* $dest/$libdir/
cp -a /$libdir/asterisk/* $dest/$libdir/asterisk/
cp -a /usr/sbin/asterisk $dest/usr/sbin
rm -rf $tf
tar -chzf $tf --transform="s/^[.]/$df/" -C $dest .
rm -rf $dest
echo "Created $tf"
fi
if $delete_coredumps_after ; then
dest=${outputdir}/${cfname}.output
for i in ${!COREDUMPS[@]} ; do
rm -rf ${dest} 2>/dev/null || :
rm -rf "${COREDUMPS[$i]}"
done
fi
if $tarball_results ; then
libdir=usr/lib
tf=/tmp/asterisk-$df-results.tar
[ -d /usr/lib64 ] && libdir+=64
echo "Creating $tf.gz"
mkdir -p ${dest}/tmp ${dest}/${libdir}/asterisk ${dest}/etc ${dest}/usr/sbin
for i in ${!COREDUMPS[@]} ; do
tar -uvf $tf "${COREDUMPS[$i]//:/-}"-{brief,full,thread1,locks}.txt 2>/dev/null
done
gzip $tf
fi
if $delete_results_after ; then
ln -s ${cf} ${dest}/tmp/${cfname}
for i in ${!COREDUMPS[@]} ; do
cp ${outputdir}/${cfname}*.txt ${dest}/tmp/
rm -rf "${COREDUMPS[$i]//:/-}"-{brief,full,thread1,locks}.txt
cp /etc/os-release ${dest}/etc/
done
if $tarball_config ; then
fi
cp -a /etc/asterisk ${dest}/etc/
fi
cp -a /${libdir}/libasterisk* ${dest}/${libdir}/
cp -a /${libdir}/asterisk/* ${dest}/${libdir}/asterisk/
cp -a /usr/sbin/asterisk ${dest}/usr/sbin
rm -rf ${tf}
tar -chzf ${tf} --transform="s/^[.]/${cfname}/" -C ${dest} .
rm -rf ${dest}
echo "Created $tf"
elif $tarball_results ; then
cfname=${cfname//:/-}
tf=${outputdir}/${cfname}.tar.gz
echo "Creating ${tf}"
dest=${outputdir}/${cfname}.output
rm -rf ${dest} 2>/dev/null || :
mkdir -p ${dest}
cp ${outputdir}/${cfname}*.txt ${dest}/
if $tarball_config ; then
mkdir -p ${dest}/etc
cp -a /etc/asterisk ${dest}/etc/
fi
tar -chzf ${tf} --transform="s/^[.]/${cfname}/" -C ${dest} .
rm -rf ${dest}
echo "Created $tf"
fi
if $delete_coredumps_after ; then
rm -rf "${cf}"
fi
if $delete_results_after ; then
rm -rf "${cf//:/-}"-{brief,full,thread1,locks}.txt
fi
done
exit
exit
@ -463,6 +501,9 @@ class DumpAsteriskCommand(gdb.Command):
try:
try:
gdb.execute("p $_siginfo", from_tty)
gdb.execute("p $_siginfo", from_tty)
gdb.execute("info signal $_siginfo.si_signo")
gdb.execute("info signal $_siginfo.si_signo")
except:
pass
try:
gdb.execute("thread apply 1 bt full", from_tty)
gdb.execute("thread apply 1 bt full", from_tty)
except:
except:
pass
pass
@ -470,6 +511,9 @@ class DumpAsteriskCommand(gdb.Command):
try:
try:
gdb.execute("p $_siginfo", from_tty)
gdb.execute("p $_siginfo", from_tty)
gdb.execute("info signal $_siginfo.si_signo")
gdb.execute("info signal $_siginfo.si_signo")
except:
pass
try:
gdb.execute("thread apply all bt", from_tty)
gdb.execute("thread apply all bt", from_tty)
except:
except:
pass
pass
@ -477,6 +521,9 @@ class DumpAsteriskCommand(gdb.Command):
try:
try:
gdb.execute("p $_siginfo", from_tty)
gdb.execute("p $_siginfo", from_tty)
gdb.execute("info signal $_siginfo.si_signo")
gdb.execute("info signal $_siginfo.si_signo")
except:
pass
try:
gdb.execute("thread apply all bt full", from_tty)
gdb.execute("thread apply all bt full", from_tty)
except:
except:
pass
pass
@ -484,6 +531,9 @@ class DumpAsteriskCommand(gdb.Command):
try:
try:
gdb.execute("p $_siginfo", from_tty)
gdb.execute("p $_siginfo", from_tty)
gdb.execute("info signal $_siginfo.si_signo")
gdb.execute("info signal $_siginfo.si_signo")
except:
pass
try:
gdb.execute("show_locks", from_tty)
gdb.execute("show_locks", from_tty)
except:
except:
pass
pass