#! /usr/bin/env bash # # crash-diag [-c] # # -c: if this flag is present, then this script was run from post-terminate # because Zeek crashed. # is the node's working directory. . `dirname $0`/zeekctl-config.sh postterminate=0 if [ "$1" = "-c" ]; then postterminate=1 shift fi if [ $# -ne 1 ]; then echo "crash-diag: wrong number of arguments" exit 1 fi if [ ! -d "$1" ]; then echo "No work dir found" exit 0 fi cd "$1" if [ $? -ne 0 ]; then exit 1 fi # Identify all core files in the current directory. We assume these # filenames contain the word "core" and do not end in ".log". core=`ls -t *core* 2> /dev/null | grep -v '\.log$'` # Choose which debugger to use. gdb_name="gdb" if [ "${os}" = "Darwin" ]; then gdb_name="lldb" elif [ "${os}" = "OpenBSD" ]; then # The default gdb fails when trying to read Zeek core files. gdb_name="egdb" fi gdb_path=`which $gdb_name 2> /dev/null` if [ -f "${zeek}" ];then zeek_version=`"${zeek}" -v 2>/dev/null | awk '{print $3}'` else zeek_version="(file not found: ${zeek})" fi # If Zeek crashed and if a core file exists, then copy the Zeek binary so that # the user has the ability to generate a backtrace in the future. if [ $postterminate -eq 1 ]; then if [ -n "$core" ]; then myzeek=${zeek} if [ "${havenfs}" = "1" ]; then myzeek=${tmpexecdir}/`basename "${zeek}"` fi cp "$myzeek" . fi fi # Output the crash report. echo # If no backtrace can be generated, then output an explanation. However, # skip this if there's no .status file, because in that case Zeek didn't run. if [ -f .status ]; then if [ -n "$gdb_path" ]; then if [ -z "$core" ]; then # Check if the system allows setting core file size to unlimited, # because this is what the run-zeek script does when it starts Zeek. ulimit -c unlimited 2> /dev/null coresize=`ulimit -c` if [ "$coresize" != "unlimited" ]; then echo "No core file found. You may need to change your system settings to" echo "allow core files." else echo "No core file found." fi echo fi else if [ -n "$core" ]; then echo "Unable to output a backtrace because $gdb_name is not installed." echo "It is recommended to install $gdb_name so that ZeekControl can output a" echo "backtrace the next time Zeek crashes." else echo "No core file found and $gdb_name is not installed. It is recommended to" echo "install $gdb_name so that ZeekControl can output a backtrace if Zeek crashes." fi echo fi fi echo Zeek $zeek_version uname -sr echo zeekplugins=`"${zeek}" -N 2>/dev/null | grep -v "(built-in)"` if [ -z "$zeekplugins" ]; then echo "Zeek plugins: (none found)" else echo "Zeek plugins:" echo "$zeekplugins" fi # Output a backtrace if we have a debugger and a core file. if [ -n "$gdb_path" ]; then if [ -n "$core" ]; then if [ "$gdb_name" = "gdb" ] || [ "$gdb_name" = "egdb" ]; then echo "thread apply all bt" >.gdb_cmds elif [ "$gdb_name" = "lldb" ]; then echo "bt all" >.gdb_cmds fi for c in "$core"; do if [ -f "$c" ]; then echo # Note: zeekctl looks for this string in order to determine # if a backtrace was output. echo "Core file: $c" if [ "$gdb_name" = "gdb" ] || [ "$gdb_name" = "egdb" ]; then $gdb_path --batch -x .gdb_cmds "${zeek}" "$c" 2>/dev/null elif [ "$gdb_name" = "lldb" ]; then $gdb_path --batch -s .gdb_cmds -f "${zeek}" -c "$c" 2>/dev/null fi fi done rm -f .gdb_cmds fi fi # Usage: # show_log # Output the last lines of . If is -1, then output the # entire file. show_log() { filename=$1 num=$2 echo if [ -f $filename ]; then echo ==== $filename if [ $num -ge 0 ]; then tail -$num $filename else cat $filename fi else echo ==== No $filename fi } show_log reporter.log 10 show_log stderr.log 10 show_log stdout.log 10 show_log .cmdline 30 show_log .env_vars 30 show_log .status 10 show_log prof.log 10 show_log packet_filter.log 30 show_log loaded_scripts.log -1