Skip to content

Instantly share code, notes, and snippets.

@angrycub
Created September 17, 2014 20:02
Show Gist options
  • Save angrycub/79ee6be7ee8264a2ff3c to your computer and use it in GitHub Desktop.
Save angrycub/79ee6be7ee8264a2ff3c to your computer and use it in GitHub Desktop.
This grabs the same OS commands as we use in riak-debug without any Riak specific commands.
#!/bin/sh
## -------------------------------------------------------------------
##
## riak-debug-lite: Gather info from a node for troubleshooting.
##
## Copyright (c) 2013 Basho Technologies, Inc. All Rights Reserved.
##
## This file is provided to you under the Apache License,
## Version 2.0 (the "License"); you may not use this file
## except in compliance with the License. You may obtain
## a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing,
## software distributed under the License is distributed on an
## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
## KIND, either express or implied. See the License for the
## specific language governing permissions and limitations
## under the License.
##
## -------------------------------------------------------------------
# If you start to think "We should execute some Erlang in here", then go work
# on Riaknostic, which is called with `riak-admin diag` below.
# /bin/sh on Solaris is not a POSIX compatible shell, but /usr/bin/ksh is.
if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then
POSIX_SHELL="true"
export POSIX_SHELL
# To support 'whoami' add /usr/ucb to path
PATH=/usr/ucb:$PATH
export PATH
exec /usr/bin/ksh $0 "$@"
fi
unset POSIX_SHELL # clear it so if we invoke other scripts, they run as ksh as well
###
### Function declarations
###
echoerr () { echo "$@" 1>&2; }
mkdir_or_die () {
# If the dir already exists, just return
[ -d "$1" ] && return
mkdir -p "$1"
if [ 0 -ne $? ]; then
echoerr "Error creating riak-debug directories. Aborting."
echoerr "$1"
exit 1
fi
}
dump () {
# first argument is the filename to hold the command output
out=$1
shift
# next argument is the base command to execute. skip dump if not available.
[ -z "`command -v $1`" ] && return
# execute the rest of the arguments as the command
$* >> "$out" 2>&1
# grab the return value
retval=$?
# put the command and the retval in the .info/$out file to aid automation.
# note: this will miss some escaping for, e.g., find, but it's not critical.
# get command that was run with `head -1 .info/$out`
# get return value from command with `tail -1 .info/$out`
echo "$*" > .info/"$out"
echo $retval >> .info/"$out"
if [ 0 -eq $retval ]; then
printf '.' 1>&2
else
printf 'E' 1>&2
fi
return $retval
}
usage () {
cat << 'EOF'
riak-debug: Gather info from a node for troubleshooting. See 'man riak-debug'.
Usage: riak-debug-lite [-s] [-e] [FILENAME | -]
-h, --help Help - you are here.
-s, --syscmds Gather general system commands.
FILENAME Output filename for the tar.gz archive. Use - to specify stdout.
Defaults: Get system commands.
Output in current directory to NODE_NAME-riak-debug.tar.gz or
HOSTNAME-riak-debug.tar.gz if NODE_NAME cannot be found.
EOF
exit
}
###
### Set up variables
###
get_syscmds=0
###
### Parse options
###
while [ -n "$1" ]; do
case "$1" in
-h|--help)
usage
;;
-s|--syscmds)
get_syscmds=1
;;
-)
# If truly specifying stdout as the output file, it should be last
if [ $# -gt 1 ]; then
echoerr "Trailing options following filename $1. Aborting."
echoerr "See 'riak-debug -h' and manpage for help."
exit 1
fi
outfile="-"
;;
*)
# Shouldn't get here until the last option, the output filename.
if [ '-' = "$outfile" ]; then
echoerr "Filename $1 given but stdout, -, already specified."
echoerr "Aborting. See 'riak-debug -h' and manpage for help."
exit 1
fi
# The filename shouldn't start with a '-'. The single character '-'
# is handled as a special case above.
if [ '-' = `echo "$1" | awk 'BEGIN {FS=""} {print $1}'` ]; then
echoerr "Unrecognized option $1. Aborting"
echoerr "See 'riak-debug -h' and manpage for help."
exit 1
fi
if [ $# -gt 1 ]; then
echoerr "Trailing options following filename $1. Aborting."
echoerr "See 'riak-debug -h' and manpage for help."
exit 1
fi
outfile="$1"
;;
esac
shift
done
###
### Finish setting up variables and overrides
###
if [ 0 -eq $(($get_syscmds)) ]; then
# Nothing specific was requested, so get everything except extracmds
get_syscmds=1
fi
start_dir="$TMPDIR"
if [ -z "$start_dir" ]; then
start_dir=/tmp
fi
# Strip any trailing slash from TMPDIR
start_dir="`echo $start_dir | sed 's#/$##'`"
debug_dir="`hostname`-riak-debug"
if [ -d "${start_dir}"/"${debug_dir}" ]; then
echoerr "Temporary directory already exists. Aborting."
echoerr "${start_dir}"/"${debug_dir}"
exit 1
fi
if [ -z "$outfile" ]; then
# If output file not specified, output to the default
outfile="`pwd`"/"${debug_dir}".tar.gz
fi
if [ '-' != "$outfile" ] && [ -f "$outfile" ]; then
echoerr "Output file already exists. Aborting."
echoerr "$outfile"
exit 1
fi
###
### Gather system commands
###
if [ 1 -eq $get_syscmds ]; then
mkdir_or_die "${start_dir}"/"${debug_dir}"/commands/.info
cd "${start_dir}"/"${debug_dir}"/commands
# System info
dump date date
dump w w
dump last last
dump hostname hostname
dump uname uname -a
dump lsb_release lsb_release
dump ps ps aux
dump vmstat vmstat 1 5
dump free free -m
dump df df
dump df_i df -i
dump dmesg dmesg
dump mount mount
dump sysctl sysctl -a
dump rpm rpm -qa
dump dpkg dpkg -l
dump pkg_info pkg_info
dump sestatus sestatus -v
dump ifconfig ifconfig -a
dump netstat_i netstat -i
dump netstat_an netstat -an
dump netstat_rn netstat -rn
dump pfctl_rules pfctl -s rules
dump pfctl_nat pfctl -s nat
# If swapctl exists, prefer it over swapon
if [ -n "`command -v swapctl`" ]; then
dump swapctl swapctl -s
else
dump swapon swapon -s
fi
BLOCKDEV=/sbin/blockdev
if [ -e $BLOCKDEV ]; then
for mount_point in `mount | egrep '^/' | awk '{print $1}'`; do
flat_point=`echo $mount_point | sed 's:/:_:g'`
dump blockdev.$flat_point $BLOCKDEV --getra $mount_point
done
else
dump blockdev._ echo $BLOCKDEV is not available
fi
# Running iptables commands if the module is not loaded can automatically
# load them. This is rarely desired and can even cause connectivity
# problems if, e.g., nf_conntrack gets autoloaded and autoenabled.
if [ -n "`command -v lsmod`" ]; then
if [ -n "`lsmod 2>/dev/null | awk '{print $1}' | grep iptable_filter`" ]; then
dump iptables_rules iptables -n -L
else
dump iptables_rules echo "iptables module not loaded"
fi
if [ -n "`lsmod 2>/dev/null | awk '{print $1}' | grep nf_conntrack`" ]; then
dump iptables_nat iptables -t nat -n -L
else
dump iptables_nat echo "nf_conntrack module not loaded"
fi
fi
if [ -f /proc/diskstats ]; then
# Linux iostat
dump iostat_linux iostat -mx 1 5
elif [ -d /proc ]; then
# No diskstats, but proc, probably Solaris or SmartOS
dump iostat_smartos iostat -xnz 1 5
else
# BSD style iostat
dump iostat_bsd iostat -dIw 1 -c 5
fi
# Dump files
[ -f /etc/release ] && dump release cat /etc/release
[ -f /etc/redhat-release ] && dump redhat_release cat /etc/redhat-release
[ -f /etc/debian_version ] && dump debian_version cat /etc/debian_version
[ -f /etc/security/limits.conf ] && dump limits.conf cat /etc/security/limits.conf
[ -f /var/log/messages ] && dump messages cat /var/log/messages
[ -f /var/log/syslog ] && dump messages cat /var/log/syslog
[ -f /proc/diskstats ] && dump diskstats cat /proc/diskstats
[ -f /proc/cpuinfo ] && dump cpuinfo cat /proc/cpuinfo
[ -f /proc/meminfo ] && dump meminfo cat /proc/meminfo
# Dump directories and finds
[ -d /dev/disk/by-id ] && dump disk_by_id ls -l /dev/disk/by-id
[ -d /sys/block ] && dump schedulers find /sys/block/ -type l -print -exec cat {}/queue/scheduler \;
[ -d /proc/net/bonding ] && dump bonding find /proc/net/bonding/ -type f -print -exec cat {} \;
[ -d /sys/class/net ] && dump rx_crc_errors find /sys/class/net/ -type l -print -exec cat {}/statistics/rx_crc_errors \;
# A bit more complicated, but let's get all of limits.d if it's there
if [ -d /etc/security/limits.d ]; then
# check to ensure there is at least something to get
if [ -n "`find /etc/security/limits.d -maxdepth 1 -name '*.conf' -print -quit`" ]; then
mkdir_or_die "${start_dir}"/"${debug_dir}"/commands/limits.d
# Mirror the directory, only copying files that match the pattern
cd /etc/security/limits.d
find . -type f -name '*.conf' -exec sh -c '
mkdir -p "$0/${1%/*}";
cp "$1" "$0/$1"
' "${start_dir}"/"${debug_dir}"/commands/limits.d {} \;
fi
fi
fi
###
### Produce the output file
###
# One last sanity check before transferring or removing anything
cd "${start_dir}"
if [ -z "$debug_dir" ] || [ ! -d "$debug_dir" ]; then
echoerr "Couldn't find ${start_dir}/${debug_dir}. Aborting"
exit 1
fi
if [ '-' = "$outfile" ]; then
# So we don't get a file literally named -
tar zcf - "${debug_dir}"
else
tar zcf "$outfile" "${debug_dir}"
# provide some indication of the output filename
printf " $outfile" 1>&2
fi
rm -rf "${debug_dir}"
# keep things looking pretty
echoerr ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment