system: Linux mars.sprixweb.com 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64
#!/bin/sh
# This program is part of Percona Toolkit: http://www.percona.com/software/
# See "COPYRIGHT, LICENSE, AND WARRANTY" at the end of this file for legal
# notices and disclaimers.
set -u
# ########################################################################
# Globals, settings, helper functions
# ########################################################################
TOOL="pt-summary"
POSIXLY_CORRECT=1
export POSIXLY_CORRECT
# ###########################################################################
# log_warn_die package
# This package is a copy without comments from the original. The original
# with comments and its test file can be found in the Bazaar repository at,
# lib/bash/log_warn_die.sh
# t/lib/bash/log_warn_die.sh
# See https://launchpad.net/percona-toolkit for more information.
# ###########################################################################
set -u
PTFUNCNAME=""
PTDEBUG="${PTDEBUG:-""}"
EXIT_STATUS=0
ts() {
TS=$(date +%F-%T | tr ':-' '_')
echo "$TS $*"
}
info() {
[ ${OPT_VERBOSE:-3} -ge 3 ] && ts "$*"
}
log() {
[ ${OPT_VERBOSE:-3} -ge 2 ] && ts "$*"
}
warn() {
[ ${OPT_VERBOSE:-3} -ge 1 ] && ts "$*" >&2
EXIT_STATUS=1
}
die() {
ts "$*" >&2
EXIT_STATUS=1
exit 1
}
_d () {
[ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(ts "$*")" >&2
}
# ###########################################################################
# End log_warn_die package
# ###########################################################################
# ###########################################################################
# parse_options package
# This package is a copy without comments from the original. The original
# with comments and its test file can be found in the Bazaar repository at,
# lib/bash/parse_options.sh
# t/lib/bash/parse_options.sh
# See https://launchpad.net/percona-toolkit for more information.
# ###########################################################################
set -u
ARGV="" # Non-option args (probably input files)
EXT_ARGV="" # Everything after -- (args for an external command)
HAVE_EXT_ARGV="" # Got --, everything else is put into EXT_ARGV
OPT_ERRS=0 # How many command line option errors
OPT_VERSION="" # If --version was specified
OPT_HELP="" # If --help was specified
PO_DIR="" # Directory with program option spec files
usage() {
local file="$1"
local usage="$(grep '^Usage: ' "$file")"
echo $usage
echo
echo "For more information, 'man $TOOL' or 'perldoc $file'."
}
usage_or_errors() {
local file="$1"
local version=""
if [ "$OPT_VERSION" ]; then
version=$(grep '^pt-[^ ]\+ [0-9]' "$file")
echo "$version"
return 1
fi
if [ "$OPT_HELP" ]; then
usage "$file"
echo
echo "Command line options:"
echo
perl -e '
use strict;
use warnings FATAL => qw(all);
my $lcol = 20; # Allow this much space for option names.
my $rcol = 80 - $lcol; # The terminal is assumed to be 80 chars wide.
my $name;
while ( <> ) {
my $line = $_;
chomp $line;
if ( $line =~ s/^long:/ --/ ) {
$name = $line;
}
elsif ( $line =~ s/^desc:// ) {
$line =~ s/ +$//mg;
my @lines = grep { $_ }
$line =~ m/(.{0,$rcol})(?:\s+|\Z)/g;
if ( length($name) >= $lcol ) {
print $name, "\n", (q{ } x $lcol);
}
else {
printf "%-${lcol}s", $name;
}
print join("\n" . (q{ } x $lcol), @lines);
print "\n";
}
}
' "$PO_DIR"/*
echo
echo "Options and values after processing arguments:"
echo
(
cd "$PO_DIR"
for opt in *; do
local varname="OPT_$(echo "$opt" | tr a-z- A-Z_)"
eval local varvalue=\$$varname
if ! grep -q "type:" "$PO_DIR/$opt" >/dev/null; then
if [ "$varvalue" -a "$varvalue" = "yes" ];
then varvalue="TRUE"
else
varvalue="FALSE"
fi
fi
printf -- " --%-30s %s" "$opt" "${varvalue:-(No value)}"
echo
done
)
return 1
fi
if [ $OPT_ERRS -gt 0 ]; then
echo
usage "$file"
return 1
fi
return 0
}
option_error() {
local err="$1"
OPT_ERRS=$(($OPT_ERRS + 1))
echo "$err" >&2
}
parse_options() {
local file="$1"
shift
ARGV=""
EXT_ARGV=""
HAVE_EXT_ARGV=""
OPT_ERRS=0
OPT_VERSION=""
OPT_HELP=""
PO_DIR="$PT_TMPDIR/po"
if [ ! -d "$PO_DIR" ]; then
mkdir "$PO_DIR"
if [ $? -ne 0 ]; then
echo "Cannot mkdir $PO_DIR" >&2
exit 1
fi
fi
rm -rf "$PO_DIR"/*
if [ $? -ne 0 ]; then
echo "Cannot rm -rf $PO_DIR/*" >&2
exit 1
fi
_parse_pod "$file" # Parse POD into program option (po) spec files
_eval_po # Eval po into existence with default values
if [ $# -ge 2 ] && [ "$1" = "--config" ]; then
shift # --config
local user_config_files="$1"
shift # that ^
local IFS=","
for user_config_file in $user_config_files; do
_parse_config_files "$user_config_file"
done
else
_parse_config_files "/etc/percona-toolkit/percona-toolkit.conf" "/etc/percona-toolkit/$TOOL.conf"
if [ "${HOME:-}" ]; then
_parse_config_files "$HOME/.percona-toolkit.conf" "$HOME/.$TOOL.conf"
fi
fi
_parse_command_line "${@:-""}"
}
_parse_pod() {
local file="$1"
PO_FILE="$file" PO_DIR="$PO_DIR" perl -e '
$/ = "";
my $file = $ENV{PO_FILE};
open my $fh, "<", $file or die "Cannot open $file: $!";
while ( defined(my $para = <$fh>) ) {
next unless $para =~ m/^=head1 OPTIONS/;
while ( defined(my $para = <$fh>) ) {
last if $para =~ m/^=head1/;
chomp;
if ( $para =~ m/^=item --(\S+)/ ) {
my $opt = $1;
my $file = "$ENV{PO_DIR}/$opt";
open my $opt_fh, ">", $file or die "Cannot open $file: $!";
print $opt_fh "long:$opt\n";
$para = <$fh>;
chomp;
if ( $para =~ m/^[a-z ]+:/ ) {
map {
chomp;
my ($attrib, $val) = split(/: /, $_);
print $opt_fh "$attrib:$val\n";
} split(/; /, $para);
$para = <$fh>;
chomp;
}
my ($desc) = $para =~ m/^([^?.]+)/;
print $opt_fh "desc:$desc.\n";
close $opt_fh;
}
}
last;
}
'
}
_eval_po() {
local IFS=":"
for opt_spec in "$PO_DIR"/*; do
local opt=""
local default_val=""
local neg=0
local size=0
while read key val; do
case "$key" in
long)
opt=$(echo $val | sed 's/-/_/g' | tr '[:lower:]' '[:upper:]')
;;
default)
default_val="$val"
;;
"short form")
;;
type)
[ "$val" = "size" ] && size=1
;;
desc)
;;
negatable)
if [ "$val" = "yes" ]; then
neg=1
fi
;;
*)
echo "Invalid attribute in $opt_spec: $line" >&2
exit 1
esac
done < "$opt_spec"
if [ -z "$opt" ]; then
echo "No long attribute in option spec $opt_spec" >&2
exit 1
fi
if [ $neg -eq 1 ]; then
if [ -z "$default_val" ] || [ "$default_val" != "yes" ]; then
echo "Option $opt_spec is negatable but not default: yes" >&2
exit 1
fi
fi
if [ $size -eq 1 -a -n "$default_val" ]; then
default_val=$(size_to_bytes $default_val)
fi
eval "OPT_${opt}"="$default_val"
done
}
_parse_config_files() {
for config_file in "${@:-""}"; do
test -f "$config_file" || continue
while read config_opt; do
echo "$config_opt" | grep '^[ ]*[^#]' >/dev/null 2>&1 || continue
config_opt="$(echo "$config_opt" | sed -e 's/^ *//g' -e 's/ *$//g' -e 's/[ ]*=[ ]*/=/' -e 's/[ ]*#.*$//')"
[ "$config_opt" = "" ] && continue
echo "$config_opt" | grep -v 'version-check' >/dev/null 2>&1 || continue
if ! [ "$HAVE_EXT_ARGV" ]; then
config_opt="--$config_opt"
fi
_parse_command_line "$config_opt"
done < "$config_file"
HAVE_EXT_ARGV="" # reset for each file
done
}
_parse_command_line() {
local opt=""
local val=""
local next_opt_is_val=""
local opt_is_ok=""
local opt_is_negated=""
local real_opt=""
local required_arg=""
local spec=""
for opt in "${@:-""}"; do
if [ "$opt" = "--" -o "$opt" = "----" ]; then
HAVE_EXT_ARGV=1
continue
fi
if [ "$HAVE_EXT_ARGV" ]; then
if [ "$EXT_ARGV" ]; then
EXT_ARGV="$EXT_ARGV $opt"
else
EXT_ARGV="$opt"
fi
continue
fi
if [ "$next_opt_is_val" ]; then
next_opt_is_val=""
if [ $# -eq 0 ] || [ $(expr "$opt" : "\-") -eq 1 ]; then
option_error "$real_opt requires a $required_arg argument"
continue
fi
val="$opt"
opt_is_ok=1
else
if [ $(expr "$opt" : "\-") -eq 0 ]; then
if [ -z "$ARGV" ]; then
ARGV="$opt"
else
ARGV="$ARGV $opt"
fi
continue
fi
real_opt="$opt"
if $(echo $opt | grep '^--no[^-]' >/dev/null); then
local base_opt=$(echo $opt | sed 's/^--no//')
if [ -f "$PT_TMPDIR/po/$base_opt" ]; then
opt_is_negated=1
opt="$base_opt"
else
opt_is_negated=""
opt=$(echo $opt | sed 's/^-*//')
fi
else
if $(echo $opt | grep '^--no-' >/dev/null); then
opt_is_negated=1
opt=$(echo $opt | sed 's/^--no-//')
else
opt_is_negated=""
opt=$(echo $opt | sed 's/^-*//')
fi
fi
if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then
val="$(echo $opt | awk -F= '{print $2}')"
opt="$(echo $opt | awk -F= '{print $1}')"
fi
if [ -f "$PT_TMPDIR/po/$opt" ]; then
spec="$PT_TMPDIR/po/$opt"
else
spec=$(grep "^short form:-$opt\$" "$PT_TMPDIR"/po/* | cut -d ':' -f 1)
if [ -z "$spec" ]; then
option_error "Unknown option: $real_opt"
continue
fi
fi
required_arg=$(cat "$spec" | awk -F: '/^type:/{print $2}')
if [ "$required_arg" ]; then
if [ "$val" ]; then
opt_is_ok=1
else
next_opt_is_val=1
fi
else
if [ "$val" ]; then
option_error "Option $real_opt does not take a value"
continue
fi
if [ "$opt_is_negated" ]; then
val=""
else
val="yes"
fi
opt_is_ok=1
fi
fi
if [ "$opt_is_ok" ]; then
opt=$(cat "$spec" | grep '^long:' | cut -d':' -f2 | sed 's/-/_/g' | tr '[:lower:]' '[:upper:]')
if grep "^type:size" "$spec" >/dev/null; then
val=$(size_to_bytes $val)
fi
eval "OPT_$opt"="'$val'"
opt=""
val=""
next_opt_is_val=""
opt_is_ok=""
opt_is_negated=""
real_opt=""
required_arg=""
spec=""
fi
done
}
size_to_bytes() {
local size="$1"
echo $size | perl -ne '%f=(B=>1, K=>1_024, M=>1_048_576, G=>1_073_741_824, T=>1_099_511_627_776); m/^(\d+)([kMGT])?/i; print $1 * $f{uc($2 || "B")};'
}
# ###########################################################################
# End parse_options package
# ###########################################################################
# ###########################################################################
# tmpdir package
# This package is a copy without comments from the original. The original
# with comments and its test file can be found in the Bazaar repository at,
# lib/bash/tmpdir.sh
# t/lib/bash/tmpdir.sh
# See https://launchpad.net/percona-toolkit for more information.
# ###########################################################################
set -u
PT_TMPDIR=""
mk_tmpdir() {
local dir="${1:-""}"
if [ -n "$dir" ]; then
if [ ! -d "$dir" ]; then
mkdir "$dir" || die "Cannot make tmpdir $dir"
fi
PT_TMPDIR="$dir"
else
local tool="${0##*/}"
local pid="$$"
PT_TMPDIR=`mktemp -d -t "${tool}.${pid}.XXXXXX"` \
|| die "Cannot make secure tmpdir"
fi
}
rm_tmpdir() {
if [ -n "$PT_TMPDIR" ] && [ -d "$PT_TMPDIR" ]; then
rm -rf "$PT_TMPDIR"
fi
PT_TMPDIR=""
}
# ###########################################################################
# End tmpdir package
# ###########################################################################
# ###########################################################################
# alt_cmds package
# This package is a copy without comments from the original. The original
# with comments and its test file can be found in the Bazaar repository at,
# lib/bash/alt_cmds.sh
# t/lib/bash/alt_cmds.sh
# See https://launchpad.net/percona-toolkit for more information.
# ###########################################################################
set -u
_seq() {
local i="$1"
awk "BEGIN { for(i=1; i<=$i; i++) print i; }"
}
_pidof() {
local cmd="$1"
if ! pidof "$cmd" 2>/dev/null; then
ps -eo pid,ucomm | awk -v comm="$cmd" '$2 == comm { print $1 }'
fi
}
_lsof() {
local pid="$1"
if ! lsof -p $pid 2>/dev/null; then
/bin/ls -l /proc/$pid/fd 2>/dev/null
fi
}
_which() {
if [ -x /usr/bin/which ]; then
/usr/bin/which "$1" 2>/dev/null | awk '{print $1}'
elif which which 1>/dev/null 2>&1; then
which "$1" 2>/dev/null | awk '{print $1}'
else
echo "$1"
fi
}
# ###########################################################################
# End alt_cmds package
# ###########################################################################
# ###########################################################################
# summary_common package
# This package is a copy without comments from the original. The original
# with comments and its test file can be found in the Bazaar repository at,
# lib/bash/summary_common.sh
# t/lib/bash/summary_common.sh
# See https://launchpad.net/percona-toolkit for more information.
# ###########################################################################
set -u
CMD_FILE="$( _which file 2>/dev/null )"
CMD_NM="$( _which nm 2>/dev/null )"
CMD_OBJDUMP="$( _which objdump 2>/dev/null )"
get_nice_of_pid () {
local pid="$1"
local niceness="$(ps -p $pid -o nice | awk '$1 !~ /[^0-9]/ {print $1; exit}')"
if [ -n "${niceness}" ]; then
echo $niceness
else
local tmpfile="$PT_TMPDIR/nice_through_c.tmp.c"
_d "Getting the niceness from ps failed, somehow. We are about to try this:"
cat <<EOC > "$tmpfile"
int main(void) {
int priority = getpriority(PRIO_PROCESS, $pid);
if ( priority == -1 && errno == ESRCH ) {
return 1;
}
else {
printf("%d\\n", priority);
return 0;
}
}
EOC
local c_comp=$(_which gcc)
if [ -z "${c_comp}" ]; then
c_comp=$(_which cc)
fi
_d "$tmpfile: $( cat "$tmpfile" )"
_d "$c_comp -xc \"$tmpfile\" -o \"$tmpfile\" && eval \"$tmpfile\""
$c_comp -xc "$tmpfile" -o "$tmpfile" 2>/dev/null && eval "$tmpfile" 2>/dev/null
if [ $? -ne 0 ]; then
echo "?"
_d "Failed to get a niceness value for $pid"
fi
fi
}
get_oom_of_pid () {
local pid="$1"
local oom_adj=""
if [ -n "${pid}" -a -e /proc/cpuinfo ]; then
if [ -s "/proc/$pid/oom_score_adj" ]; then
oom_adj=$(cat "/proc/$pid/oom_score_adj" 2>/dev/null)
_d "For $pid, the oom value is $oom_adj, retreived from oom_score_adj"
else
oom_adj=$(cat "/proc/$pid/oom_adj" 2>/dev/null)
_d "For $pid, the oom value is $oom_adj, retreived from oom_adj"
fi
fi
if [ -n "${oom_adj}" ]; then
echo "${oom_adj}"
else
echo "?"
_d "Can't find the oom value for $pid"
fi
}
has_symbols () {
local executable="$(_which "$1")"
local has_symbols=""
if [ "${CMD_FILE}" ] \
&& [ "$($CMD_FILE "${executable}" | grep 'not stripped' )" ]; then
has_symbols=1
elif [ "${CMD_NM}" ] \
|| [ "${CMD_OBJDMP}" ]; then
if [ "${CMD_NM}" ] \
&& [ !"$("${CMD_NM}" -- "${executable}" 2>&1 | grep 'File format not recognized' )" ]; then
if [ -z "$( $CMD_NM -- "${executable}" 2>&1 | grep ': no symbols' )" ]; then
has_symbols=1
fi
elif [ -z "$("${CMD_OBJDUMP}" -t -- "${executable}" | grep '^no symbols$' )" ]; then
has_symbols=1
fi
fi
if [ "${has_symbols}" ]; then
echo "Yes"
else
echo "No"
fi
}
setup_data_dir () {
local existing_dir="$1"
local data_dir=""
if [ -z "$existing_dir" ]; then
mkdir "$PT_TMPDIR/data" || die "Cannot mkdir $PT_TMPDIR/data"
data_dir="$PT_TMPDIR/data"
else
if [ ! -d "$existing_dir" ]; then
mkdir "$existing_dir" || die "Cannot mkdir $existing_dir"
elif [ "$( ls -A "$existing_dir" )" ]; then
die "--save-samples directory isn't empty, halting."
fi
touch "$existing_dir/test" || die "Cannot write to $existing_dir"
rm "$existing_dir/test" || die "Cannot rm $existing_dir/test"
data_dir="$existing_dir"
fi
echo "$data_dir"
}
get_var () {
local varname="$1"
local file="$2"
awk -v pattern="${varname}" '$1 == pattern { if (length($2)) { len = length($1); print substr($0, len+index(substr($0, len+1), $2)) } }' "${file}"
}
# ###########################################################################
# End summary_common package
# ###########################################################################
# ###########################################################################
# report_formatting package
# This package is a copy without comments from the original. The original
# with comments and its test file can be found in the Bazaar repository at,
# lib/bash/report_formatting.sh
# t/lib/bash/report_formatting.sh
# See https://launchpad.net/percona-toolkit for more information.
# ###########################################################################
set -u
POSIXLY_CORRECT=1
export POSIXLY_CORRECT
fuzzy_formula='
rounded = 0;
if (fuzzy_var <= 10 ) {
rounded = 1;
}
factor = 1;
while ( rounded == 0 ) {
if ( fuzzy_var <= 50 * factor ) {
fuzzy_var = sprintf("%.0f", fuzzy_var / (5 * factor)) * 5 * factor;
rounded = 1;
}
else if ( fuzzy_var <= 100 * factor) {
fuzzy_var = sprintf("%.0f", fuzzy_var / (10 * factor)) * 10 * factor;
rounded = 1;
}
else if ( fuzzy_var <= 250 * factor) {
fuzzy_var = sprintf("%.0f", fuzzy_var / (25 * factor)) * 25 * factor;
rounded = 1;
}
factor = factor * 10;
}'
fuzz () {
awk -v fuzzy_var="$1" "BEGIN { ${fuzzy_formula} print fuzzy_var;}"
}
fuzzy_pct () {
local pct="$(awk -v one="$1" -v two="$2" 'BEGIN{ if (two > 0) { printf "%d", one/two*100; } else {print 0} }')";
echo "$(fuzz "${pct}")%"
}
section () {
local str="$1"
awk -v var="${str} _" 'BEGIN {
line = sprintf("# %-60s", var);
i = index(line, "_");
x = substr(line, i);
gsub(/[_ \t]/, "#", x);
printf("%s%s\n", substr(line, 1, i-1), x);
}'
}
NAME_VAL_LEN=12
name_val () {
printf "%+*s | %s\n" "${NAME_VAL_LEN}" "$1" "$2"
}
shorten() {
local num="$1"
local prec="${2:-2}"
local div="${3:-1024}"
echo "$num" | awk -v prec="$prec" -v div="$div" '
{
num = $1;
unit = num >= 1125899906842624 ? "P" \
: num >= 1099511627776 ? "T" \
: num >= 1073741824 ? "G" \
: num >= 1048576 ? "M" \
: num >= 1024 ? "k" \
: "";
while ( num >= div ) {
num /= div;
}
printf "%.*f%s", prec, num, unit;
}
'
}
group_concat () {
sed -e '{H; $!d;}' -e 'x' -e 's/\n[[:space:]]*\([[:digit:]]*\)[[:space:]]*/, \1x/g' -e 's/[[:space:]][[:space:]]*/ /g' -e 's/, //' "${1}"
}
# ###########################################################################
# End report_formatting package
# ###########################################################################
# ###########################################################################
# collect_system_info package
# This package is a copy without comments from the original. The original
# with comments and its test file can be found in the Bazaar repository at,
# lib/bash/collect_system_info.sh
# t/lib/bash/collect_system_info.sh
# See https://launchpad.net/percona-toolkit for more information.
# ###########################################################################
set -u
setup_commands () {
CMD_SYSCTL="$(_which sysctl 2>/dev/null )"
CMD_DMIDECODE="$(_which dmidecode 2>/dev/null )"
CMD_ZONENAME="$(_which zonename 2>/dev/null )"
CMD_DMESG="$(_which dmesg 2>/dev/null )"
CMD_FILE="$(_which file 2>/dev/null )"
CMD_LSPCI="$(_which lspci 2>/dev/null )"
CMD_PRTDIAG="$(_which prtdiag 2>/dev/null )"
CMD_SMBIOS="$(_which smbios 2>/dev/null )"
CMD_GETENFORCE="$(_which getenforce 2>/dev/null )"
CMD_PRTCONF="$(_which prtconf 2>/dev/null )"
CMD_LVS="$(_which lvs 2>/dev/null)"
CMD_VGS="$(_which vgs 2>/dev/null)"
CMD_PRSTAT="$(_which prstat 2>/dev/null)"
CMD_ISAINFO="$(_which isainfo 2>/dev/null)"
CMD_TOP="$(_which top 2>/dev/null)"
CMD_ARCCONF="$( _which arcconf 2>/dev/null )"
CMD_HPACUCLI="$( _which hpacucli 2>/dev/null )"
CMD_MEGACLI64="$( _which MegaCli64 2>/dev/null )"
CMD_VMSTAT="$(_which vmstat 2>/dev/null)"
CMD_IP="$( _which ip 2>/dev/null )"
CMD_NETSTAT="$( _which netstat 2>/dev/null )"
CMD_PSRINFO="$( _which psrinfo 2>/dev/null )"
CMD_SWAPCTL="$( _which swapctl 2>/dev/null )"
CMD_LSB_RELEASE="$( _which lsb_release 2>/dev/null )"
CMD_ETHTOOL="$( _which ethtool 2>/dev/null )"
CMD_GETCONF="$( _which getconf 2>/dev/null )"
CMD_FIO_STATUS="$( _which fio-status 2>/dev/null )"
}
collect_system_data () { local PTFUNCNAME=collect_system_data;
local data_dir="$1"
if [ -r /var/log/dmesg -a -s /var/log/dmesg ]; then
cat "/var/log/dmesg" > "$data_dir/dmesg_file"
fi
$CMD_SYSCTL -a > "$data_dir/sysctl" 2>/dev/null
if [ "${CMD_LSPCI}" ]; then
$CMD_LSPCI > "$data_dir/lspci_file" 2>/dev/null
fi
local platform="$(uname -s)"
echo "platform $platform" >> "$data_dir/summary"
echo "hostname $(uname -n)" >> "$data_dir/summary"
uptime >> "$data_dir/uptime"
processor_info "$data_dir"
find_release_and_kernel "$platform" >> "$data_dir/summary"
cpu_and_os_arch "$platform" >> "$data_dir/summary"
find_virtualization "$platform" "$data_dir/dmesg_file" "$data_dir/lspci_file" >> "$data_dir/summary"
dmidecode_system_info >> "$data_dir/summary"
if [ "${platform}" = "SunOS" -a "${CMD_ZONENAME}" ]; then
echo "zonename $($CMD_ZONENAME)" >> "$data_dir/summary"
fi
if [ -x /lib/libc.so.6 ]; then
echo "compiler $(/lib/libc.so.6 | grep 'Compiled by' | cut -c13-)" >> "$data_dir/summary"
fi
local rss=$(ps -eo rss 2>/dev/null | awk '/[0-9]/{total += $1 * 1024} END {print total}')
echo "rss ${rss}" >> "$data_dir/summary"
[ "$CMD_DMIDECODE" ] && $CMD_DMIDECODE > "$data_dir/dmidecode" 2>/dev/null
find_memory_stats "$platform" > "$data_dir/memory"
[ "$OPT_SUMMARIZE_MOUNTS" ] && mounted_fs_info "$platform" > "$data_dir/mounted_fs"
raid_controller "$data_dir/dmesg_file" "$data_dir/lspci_file" >> "$data_dir/summary"
local controller="$(get_var raid_controller "$data_dir/summary")"
propietary_raid_controller "$data_dir/raid-controller" "$data_dir/summary" "$data_dir" "$controller"
[ "${platform}" = "Linux" ] && linux_exclusive_collection "$data_dir"
if [ "$CMD_IP" -a "$OPT_SUMMARIZE_NETWORK" ]; then
$CMD_IP -s link > "$data_dir/ip"
network_device_info "$data_dir/ip" > "$data_dir/network_devices"
fi
[ "$CMD_SWAPCTL" ] && $CMD_SWAPCTL -s > "$data_dir/swapctl"
if [ "$OPT_SUMMARIZE_PROCESSES" ]; then
top_processes > "$data_dir/processes"
notable_processes_info > "$data_dir/notable_procs"
if [ "$CMD_VMSTAT" ]; then
touch "$data_dir/vmstat"
(
$CMD_VMSTAT 1 $OPT_SLEEP > "$data_dir/vmstat"
) &
fi
fi
fio_status_minus_a "$data_dir/fusion-io_card"
for file in $data_dir/*; do
[ "$file" = "vmstat" ] && continue
[ ! -s "$file" ] && rm "$file"
done
}
fio_status_minus_a () {
local file="$1"
local full_output="${file}_original_output"
[ -z "$CMD_FIO_STATUS" ] && return;
$CMD_FIO_STATUS -a > "$full_output"
cat <<'EOP' > "$PT_TMPDIR/fio_status_format.pl"
my $tmp_adapter;
while (<>) {
if ( /Fusion-io driver version:\s*(.+)/ ) {
print "driver_version $1"
}
next unless /^Adapter:(.+)/;
$tmp_adapter = $1;
last;
}
$/ = "\nAdapter: ";
$_ = $tmp_adapter . "\n" . scalar(<>);
my @adapters;
do {
my ($adapter, $adapter_general) = /\s*(.+)\s*\n\s*(.+)/m;
$adapter =~ tr/ /:/;
$adapter .= "::" . scalar(@adapters); # To differentiate two adapters with the same name
push @adapters, $adapter;
my ($connected_modules) = /Connected \S+ modules?:\s*\n(.+?\n)\n/smg;
my @connected_modules = $connected_modules =~ /\s+([^:]+):.+\n/g;
print "${adapter}_general $adapter_general";
print "${adapter}_modules @connected_modules";
for my $module (@connected_modules) {
my ($rest, $attached, $general, $firmware, $temperature, $media_status) = /(
^ \s* $module \s+ (Attached[^\n]+) \n
\s+ ([^\n]+) \n # All the second line
.+? (Firmware\s+[^\n]+) \n
.+? (Internal \s+ temperature:[^\n]+) \n
.+? ((?:Media | Reserve \s+ space) \s+ status:[^\n]+) \n
.+?(?:\n\n|\z)
)/xsm;
my ($pbw) = $rest =~ /.+?(Rated \s+ PBW:[^\n]+)/xsm;
print "${adapter}_${module}_attached_as $attached";
print "${adapter}_${module}_general $general";
print "${adapter}_${module}_firmware $firmware";
print "${adapter}_${module}_media_status $media_status";
print "${adapter}_${module}_temperature $temperature";
print "${adapter}_${module}_rated_pbw $pbw" if $pbw;
}
} while <>;
print "adapters @adapters\n";
exit;
EOP
perl -wln "$PT_TMPDIR/fio_status_format.pl" "$full_output" > "$file"
}
linux_exclusive_collection () { local PTFUNCNAME=linux_exclusive_collection;
local data_dir="$1"
echo "threading $(getconf GNU_LIBPTHREAD_VERSION)" >> "$data_dir/summary"
local getenforce=""
[ "$CMD_GETENFORCE" ] && getenforce="$($CMD_GETENFORCE 2>&1)"
echo "getenforce ${getenforce:-"No SELinux detected"}" >> "$data_dir/summary"
if [ -e "$data_dir/sysctl" ]; then
echo "swappiness $(awk '/vm.swappiness/{print $3}' "$data_dir/sysctl")" >> "$data_dir/summary"
local dirty_ratio="$(awk '/vm.dirty_ratio/{print $3}' "$data_dir/sysctl")"
local dirty_bg_ratio="$(awk '/vm.dirty_background_ratio/{print $3}' "$data_dir/sysctl")"
if [ "$dirty_ratio" -a "$dirty_bg_ratio" ]; then
echo "dirtypolicy $dirty_ratio, $dirty_bg_ratio" >> "$data_dir/summary"
fi
local dirty_bytes="$(awk '/vm.dirty_bytes/{print $3}' "$data_dir/sysctl")"
if [ "$dirty_bytes" ]; then
echo "dirtystatus $(awk '/vm.dirty_bytes/{print $3}' "$data_dir/sysctl"), $(awk '/vm.dirty_background_bytes/{print $3}' "$data_dir/sysctl")" >> "$data_dir/summary"
fi
fi
schedulers_and_queue_size "$data_dir/summary" > "$data_dir/partitioning"
for file in dentry-state file-nr inode-nr; do
echo "${file} $(cat /proc/sys/fs/${file} 2>&1)" >> "$data_dir/summary"
done
[ "$CMD_LVS" -a -x "$CMD_LVS" ] && $CMD_LVS 1>"$data_dir/lvs" 2>"$data_dir/lvs.stderr"
[ "$CMD_VGS" -a -x "$CMD_VGS" ] && \
$CMD_VGS -o vg_name,vg_size,vg_free 2>/dev/null > "$data_dir/vgs"
[ "$CMD_NETSTAT" -a "$OPT_SUMMARIZE_NETWORK" ] && \
$CMD_NETSTAT -antp > "$data_dir/netstat" 2>/dev/null
}
network_device_info () {
local ip_minus_s_file="$1"
if [ "$CMD_ETHTOOL" ]; then
local tempfile="$PT_TMPDIR/ethtool_output_temp"
for device in $( awk '/^[1-9]/{ print $2 }' "$ip_minus_s_file" \
| awk -F: '{print $1}' \
| grep -v '^lo\|^in\|^gr' \
| sort -u ); do
ethtool $device > "$tempfile" 2>/dev/null
if ! grep -q 'No data available' "$tempfile"; then
cat "$tempfile"
fi
done
fi
}
find_release_and_kernel () { local PTFUNCNAME=find_release_and_kernel;
local platform="$1"
local kernel=""
local release=""
if [ "${platform}" = "Linux" ]; then
kernel="$(uname -r)"
if [ -e /etc/fedora-release ]; then
release=$(cat /etc/fedora-release);
elif [ -e /etc/redhat-release ]; then
release=$(cat /etc/redhat-release);
elif [ -e /etc/system-release ]; then
release=$(cat /etc/system-release);
elif [ "$CMD_LSB_RELEASE" ]; then
release="$($CMD_LSB_RELEASE -ds) ($($CMD_LSB_RELEASE -cs))"
elif [ -e /etc/lsb-release ]; then
release=$(grep DISTRIB_DESCRIPTION /etc/lsb-release |awk -F'=' '{print $2}' |sed 's#"##g');
elif [ -e /etc/debian_version ]; then
release="Debian-based version $(cat /etc/debian_version)";
if [ -e /etc/apt/sources.list ]; then
local code=` awk '/^deb/ {print $3}' /etc/apt/sources.list \
| awk -F/ '{print $1}'| awk 'BEGIN {FS="|"}{print $1}' \
| sort | uniq -c | sort -rn | head -n1 | awk '{print $2}'`
release="${release} (${code})"
fi
elif ls /etc/*release >/dev/null 2>&1; then
if grep -q DISTRIB_DESCRIPTION /etc/*release; then
release=$(grep DISTRIB_DESCRIPTION /etc/*release | head -n1);
else
release=$(cat /etc/*release | head -n1);
fi
fi
elif [ "${platform}" = "FreeBSD" ] \
|| [ "${platform}" = "NetBSD" ] \
|| [ "${platform}" = "OpenBSD" ]; then
release="$(uname -r)"
kernel="$($CMD_SYSCTL -n "kern.osrevision")"
elif [ "${platform}" = "SunOS" ]; then
release="$(head -n1 /etc/release)"
if [ -z "${release}" ]; then
release="$(uname -r)"
fi
kernel="$(uname -v)"
fi
echo "kernel $kernel"
echo "release $release"
}
cpu_and_os_arch () { local PTFUNCNAME=cpu_and_os_arch;
local platform="$1"
local CPU_ARCH='32-bit'
local OS_ARCH='32-bit'
if [ "${platform}" = "Linux" ]; then
if grep -q ' lm ' /proc/cpuinfo; then
CPU_ARCH='64-bit'
fi
elif [ "${platform}" = "FreeBSD" ] || [ "${platform}" = "NetBSD" ]; then
if $CMD_SYSCTL "hw.machine_arch" | grep -v 'i[36]86' >/dev/null; then
CPU_ARCH='64-bit'
fi
elif [ "${platform}" = "OpenBSD" ]; then
if $CMD_SYSCTL "hw.machine" | grep -v 'i[36]86' >/dev/null; then
CPU_ARCH='64-bit'
fi
elif [ "${platform}" = "SunOS" ]; then
if $CMD_ISAINFO -b | grep 64 >/dev/null ; then
CPU_ARCH="64-bit"
fi
fi
if [ -z "$CMD_FILE" ]; then
if [ "$CMD_GETCONF" ] && $CMD_GETCONF LONG_BIT 1>/dev/null 2>&1; then
OS_ARCH="$($CMD_GETCONF LONG_BIT 2>/dev/null)-bit"
else
OS_ARCH='N/A'
fi
elif $CMD_FILE /bin/sh | grep '64-bit' >/dev/null; then
OS_ARCH='64-bit'
fi
echo "CPU_ARCH $CPU_ARCH"
echo "OS_ARCH $OS_ARCH"
}
find_virtualization () { local PTFUNCNAME=find_virtualization;
local platform="$1"
local dmesg_file="$2"
local lspci_file="$3"
local tempfile="$PT_TMPDIR/find_virtualziation.tmp"
local virt=""
if [ -s "$dmesg_file" ]; then
virt="$(find_virtualization_dmesg "$dmesg_file")"
fi
if [ -z "${virt}" ] && [ -s "$lspci_file" ]; then
if grep -qi "virtualbox" "$lspci_file" ; then
virt="VirtualBox"
elif grep -qi "vmware" "$lspci_file" ; then
virt="VMWare"
fi
elif [ "${platform}" = "FreeBSD" ]; then
if ps -o stat | grep J ; then
virt="FreeBSD Jail"
fi
elif [ "${platform}" = "SunOS" ]; then
if [ "$CMD_PRTDIAG" ] && $CMD_PRTDIAG > "$tempfile" 2>/dev/null; then
virt="$(find_virtualization_generic "$tempfile" )"
elif [ "$CMD_SMBIOS" ] && $CMD_SMBIOS > "$tempfile" 2>/dev/null; then
virt="$(find_virtualization_generic "$tempfile" )"
fi
elif [ -e /proc/user_beancounters ]; then
virt="OpenVZ/Virtuozzo"
fi
echo "virt ${virt:-"No virtualization detected"}"
}
find_virtualization_generic() { local PTFUNCNAME=find_virtualization_generic;
local file="$1"
if grep -i -e "virtualbox" "$file" >/dev/null; then
echo "VirtualBox"
elif grep -i -e "vmware" "$file" >/dev/null; then
echo "VMWare"
fi
}
find_virtualization_dmesg () { local PTFUNCNAME=find_virtualization_dmesg;
local file="$1"
if grep -qi -e "vmware" -e "vmxnet" -e 'paravirtualized kernel on vmi' "${file}"; then
echo "VMWare";
elif grep -qi -e 'paravirtualized kernel on xen' -e 'Xen virtual console' "${file}"; then
echo "Xen";
elif grep -qi "qemu" "${file}"; then
echo "QEmu";
elif grep -qi 'paravirtualized kernel on KVM' "${file}"; then
echo "KVM";
elif grep -q "VBOX" "${file}"; then
echo "VirtualBox";
elif grep -qi 'hd.: Virtual .., ATA.*drive' "${file}"; then
echo "Microsoft VirtualPC";
fi
}
dmidecode_system_info () { local PTFUNCNAME=dmidecode_system_info;
if [ "${CMD_DMIDECODE}" ]; then
local vendor="$($CMD_DMIDECODE -s "system-manufacturer" 2>/dev/null | sed 's/ *$//g')"
echo "vendor ${vendor}"
if [ "${vendor}" ]; then
local product="$($CMD_DMIDECODE -s "system-product-name" 2>/dev/null | sed 's/ *$//g')"
local version="$($CMD_DMIDECODE -s "system-version" 2>/dev/null | sed 's/ *$//g')"
local chassis="$($CMD_DMIDECODE -s "chassis-type" 2>/dev/null | sed 's/ *$//g')"
local servicetag="$($CMD_DMIDECODE -s "system-serial-number" 2>/dev/null | sed 's/ *$//g')"
local system="${vendor}; ${product}; v${version} (${chassis})"
echo "system ${system}"
echo "servicetag ${servicetag:-"Not found"}"
fi
fi
}
find_memory_stats () { local PTFUNCNAME=find_memory_stats;
local platform="$1"
if [ "${platform}" = "Linux" ]; then
free -b
cat /proc/meminfo
elif [ "${platform}" = "SunOS" ]; then
$CMD_PRTCONF | awk -F: '/Memory/{print $2}'
fi
}
mounted_fs_info () { local PTFUNCNAME=mounted_fs_info;
local platform="$1"
if [ "${platform}" != "SunOS" ]; then
local cmd="df -h"
if [ "${platform}" = "Linux" ]; then
cmd="df -h -P"
fi
$cmd | sort > "$PT_TMPDIR/mounted_fs_info.tmp"
mount | sort | join "$PT_TMPDIR/mounted_fs_info.tmp" -
fi
}
raid_controller () { local PTFUNCNAME=raid_controller;
local dmesg_file="$1"
local lspci_file="$2"
local tempfile="$PT_TMPDIR/raid_controller.tmp"
local controller=""
if [ -s "$lspci_file" ]; then
controller="$(find_raid_controller_lspci "$lspci_file")"
fi
if [ -z "${controller}" ] && [ -s "$dmesg_file" ]; then
controller="$(find_raid_controller_dmesg "$dmesg_file")"
fi
echo "raid_controller ${controller:-"No RAID controller detected"}"
}
find_raid_controller_dmesg () { local PTFUNCNAME=find_raid_controller_dmesg;
local file="$1"
local pat='scsi[0-9].*: .*'
if grep -qi "${pat}megaraid" "${file}"; then
echo 'LSI Logic MegaRAID SAS'
elif grep -q "Fusion MPT SAS" "${file}"; then
echo 'Fusion-MPT SAS'
elif grep -q "${pat}aacraid" "${file}"; then
echo 'AACRAID'
elif grep -q "${pat}3ware [0-9]* Storage Controller" "${file}"; then
echo '3Ware'
fi
}
find_raid_controller_lspci () { local PTFUNCNAME=find_raid_controller_lspci;
local file="$1"
if grep -q "RAID bus controller: LSI Logic / Symbios Logic MegaRAID SAS" "${file}" \
|| grep -q "RAID bus controller: LSI Logic / Symbios Logic LSI MegaSAS" $file; then
echo 'LSI Logic MegaRAID SAS'
elif grep -q "Fusion-MPT SAS" "${file}"; then
echo 'Fusion-MPT SAS'
elif grep -q "RAID bus controller: LSI Logic / Symbios Logic Unknown" "${file}"; then
echo 'LSI Logic Unknown'
elif grep -q "RAID bus controller: Adaptec AAC-RAID" "${file}"; then
echo 'AACRAID'
elif grep -q "3ware [0-9]* Storage Controller" "${file}"; then
echo '3Ware'
elif grep -q "Hewlett-Packard Company Smart Array" "${file}"; then
echo 'HP Smart Array'
elif grep -q " RAID bus controller: " "${file}"; then
awk -F: '/RAID bus controller\:/ {print $3" "$5" "$6}' "${file}"
fi
}
schedulers_and_queue_size () { local PTFUNCNAME=schedulers_and_queue_size;
local file="$1"
local disks="$(ls /sys/block/ | grep -v -e ram -e loop -e 'fd[0-9]' | xargs echo)"
echo "internal::disks $disks" >> "$file"
for disk in $disks; do
if [ -e "/sys/block/${disk}/queue/scheduler" ]; then
echo "internal::${disk} $(cat /sys/block/${disk}/queue/scheduler | grep -o '\[.*\]') $(cat /sys/block/${disk}/queue/nr_requests)" >> "$file"
fdisk -l "/dev/${disk}" 2>/dev/null
fi
done
}
top_processes () { local PTFUNCNAME=top_processes;
if [ "$CMD_PRSTAT" ]; then
$CMD_PRSTAT | head
elif [ "$CMD_TOP" ]; then
local cmd="$CMD_TOP -bn 1"
if [ "${platform}" = "FreeBSD" ] \
|| [ "${platform}" = "NetBSD" ] \
|| [ "${platform}" = "OpenBSD" ]; then
cmd="$CMD_TOP -b -d 1"
fi
$cmd \
| sed -e 's# *$##g' -e '/./{H;$!d;}' -e 'x;/PID/!d;' \
| grep . \
| head
fi
}
notable_processes_info () { local PTFUNCNAME=notable_processes_info;
local format="%5s %+2d %s\n"
local sshd_pid=$(ps -eo pid,args | awk '$2 ~ /\/usr\/sbin\/sshd/ { print $1; exit }')
echo " PID OOM COMMAND"
if [ "$sshd_pid" ]; then
printf "$format" "$sshd_pid" "$(get_oom_of_pid $sshd_pid)" "sshd"
else
printf "%5s %3s %s\n" "?" "?" "sshd doesn't appear to be running"
fi
local PTDEBUG=""
ps -eo pid,ucomm | grep '^[0-9]' | while read pid proc; do
[ "$sshd_pid" ] && [ "$sshd_pid" = "$pid" ] && continue
local oom="$(get_oom_of_pid $pid)"
if [ "$oom" ] && [ "$oom" != "?" ] && [ "$oom" = "-17" ]; then
printf "$format" "$pid" "$oom" "$proc"
fi
done
}
processor_info () { local PTFUNCNAME=processor_info;
local data_dir="$1"
if [ -f /proc/cpuinfo ]; then
cat /proc/cpuinfo > "$data_dir/proc_cpuinfo_copy" 2>/dev/null
elif [ "${platform}" = "SunOS" ]; then
$CMD_PSRINFO -v > "$data_dir/psrinfo_minus_v"
fi
}
propietary_raid_controller () { local PTFUNCNAME=propietary_raid_controller;
local file="$1"
local variable_file="$2"
local data_dir="$3"
local controller="$4"
notfound=""
if [ "${controller}" = "AACRAID" ]; then
if [ -z "$CMD_ARCCONF" ]; then
notfound="e.g. http://www.adaptec.com/en-US/support/raid/scsi_raid/ASR-2120S/"
elif $CMD_ARCCONF getconfig 1 > "$file" 2>/dev/null; then
echo "internal::raid_opt 1" >> "$variable_file"
fi
elif [ "${controller}" = "HP Smart Array" ]; then
if [ -z "$CMD_HPACUCLI" ]; then
notfound="your package repository or the manufacturer's website"
elif $CMD_HPACUCLI ctrl all show config > "$file" 2>/dev/null; then
echo "internal::raid_opt 2" >> "$variable_file"
fi
elif [ "${controller}" = "LSI Logic MegaRAID SAS" ]; then
if [ -z "$CMD_MEGACLI64" ]; then
notfound="your package repository or the manufacturer's website"
else
echo "internal::raid_opt 3" >> "$variable_file"
$CMD_MEGACLI64 -AdpAllInfo -aALL -NoLog > "$data_dir/lsi_megaraid_adapter_info.tmp" 2>/dev/null
$CMD_MEGACLI64 -AdpBbuCmd -GetBbuStatus -aALL -NoLog > "$data_dir/lsi_megaraid_bbu_status.tmp" 2>/dev/null
$CMD_MEGACLI64 -LdPdInfo -aALL -NoLog > "$data_dir/lsi_megaraid_devices.tmp" 2>/dev/null
fi
fi
if [ "${notfound}" ]; then
echo "internal::raid_opt 0" >> "$variable_file"
echo " RAID controller software not found; try getting it from" > "$file"
echo " ${notfound}" >> "$file"
fi
}
# ###########################################################################
# End collect_system_info package
# ###########################################################################
# ###########################################################################
# report_system_info package
# This package is a copy without comments from the original. The original
# with comments and its test file can be found in the Bazaar repository at,
# lib/bash/report_system_info.sh
# t/lib/bash/report_system_info.sh
# See https://launchpad.net/percona-toolkit for more information.
# ###########################################################################
set -u
parse_proc_cpuinfo () { local PTFUNCNAME=parse_proc_cpuinfo;
local file="$1"
local virtual="$(grep -c ^processor "${file}")";
local physical="$(grep 'physical id' "${file}" | sort -u | wc -l)";
local cores="$(grep 'cpu cores' "${file}" | head -n 1 | cut -d: -f2)";
[ "${physical}" = "0" ] && physical="${virtual}"
[ -z "${cores}" ] && cores=0
cores=$((${cores} * ${physical}));
local htt=""
if [ ${cores} -gt 0 -a $cores -lt $virtual ]; then htt=yes; else htt=no; fi
name_val "Processors" "physical = ${physical}, cores = ${cores}, virtual = ${virtual}, hyperthreading = ${htt}"
awk -F: '/cpu MHz/{print $2}' "${file}" \
| sort | uniq -c > "$PT_TMPDIR/parse_proc_cpuinfo_cpu.unq"
name_val "Speeds" "$(group_concat "$PT_TMPDIR/parse_proc_cpuinfo_cpu.unq")"
awk -F: '/model name/{print $2}' "${file}" \
| sort | uniq -c > "$PT_TMPDIR/parse_proc_cpuinfo_model.unq"
name_val "Models" "$(group_concat "$PT_TMPDIR/parse_proc_cpuinfo_model.unq")"
awk -F: '/cache size/{print $2}' "${file}" \
| sort | uniq -c > "$PT_TMPDIR/parse_proc_cpuinfo_cache.unq"
name_val "Caches" "$(group_concat "$PT_TMPDIR/parse_proc_cpuinfo_cache.unq")"
}
parse_sysctl_cpu_freebsd() { local PTFUNCNAME=parse_sysctl_cpu_freebsd;
local file="$1"
[ -e "$file" ] || return;
local virtual="$(awk '/hw.ncpu/{print $2}' "$file")"
name_val "Processors" "virtual = ${virtual}"
name_val "Speeds" "$(awk '/hw.clockrate/{print $2}' "$file")"
name_val "Models" "$(awk -F: '/hw.model/{print substr($2, 2)}' "$file")"
}
parse_sysctl_cpu_netbsd() { local PTFUNCNAME=parse_sysctl_cpu_netbsd;
local file="$1"
[ -e "$file" ] || return
local virtual="$(awk '/hw.ncpu /{print $NF}' "$file")"
name_val "Processors" "virtual = ${virtual}"
name_val "Models" "$(awk -F: '/hw.model/{print $3}' "$file")"
}
parse_sysctl_cpu_openbsd() { local PTFUNCNAME=parse_sysctl_cpu_openbsd;
local file="$1"
[ -e "$file" ] || return
name_val "Processors" "$(awk -F= '/hw.ncpu=/{print $2}' "$file")"
name_val "Speeds" "$(awk -F= '/hw.cpuspeed/{print $2}' "$file")"
name_val "Models" "$(awk -F= '/hw.model/{print substr($2, 1, index($2, " "))}' "$file")"
}
parse_psrinfo_cpus() { local PTFUNCNAME=parse_psrinfo_cpus;
local file="$1"
[ -e "$file" ] || return
name_val "Processors" "$(grep -c 'Status of .* processor' "$file")"
awk '/operates at/ {
start = index($0, " at ") + 4;
end = length($0) - start - 4
print substr($0, start, end);
}' "$file" | sort | uniq -c > "$PT_TMPDIR/parse_psrinfo_cpus.tmp"
name_val "Speeds" "$(group_concat "$PT_TMPDIR/parse_psrinfo_cpus.tmp")"
}
parse_free_minus_b () { local PTFUNCNAME=parse_free_minus_b;
local file="$1"
[ -e "$file" ] || return
local physical=$(awk '/Mem:/{print $3}' "${file}")
local swap_alloc=$(awk '/Swap:/{print $2}' "${file}")
local swap_used=$(awk '/Swap:/{print $3}' "${file}")
local virtual=$(shorten $(($physical + $swap_used)) 1)
name_val "Total" $(shorten $(awk '/Mem:/{print $2}' "${file}") 1)
name_val "Free" $(shorten $(awk '/Mem:/{print $4}' "${file}") 1)
name_val "Used" "physical = $(shorten ${physical} 1), swap allocated = $(shorten ${swap_alloc} 1), swap used = $(shorten ${swap_used} 1), virtual = ${virtual}"
name_val "Buffers" $(shorten $(awk '/Mem:/{print $6}' "${file}") 1)
name_val "Caches" $(shorten $(awk '/Mem:/{print $7}' "${file}") 1)
name_val "Dirty" "$(awk '/Dirty:/ {print $2, $3}' "${file}")"
}
parse_memory_sysctl_freebsd() { local PTFUNCNAME=parse_memory_sysctl_freebsd;
local file="$1"
[ -e "$file" ] || return
local physical=$(awk '/hw.realmem:/{print $2}' "${file}")
local mem_hw=$(awk '/hw.physmem:/{print $2}' "${file}")
local mem_used=$(awk '
/hw.physmem/ { mem_hw = $2; }
/vm.stats.vm.v_inactive_count/ { mem_inactive = $2; }
/vm.stats.vm.v_cache_count/ { mem_cache = $2; }
/vm.stats.vm.v_free_count/ { mem_free = $2; }
/hw.pagesize/ { pagesize = $2; }
END {
mem_inactive *= pagesize;
mem_cache *= pagesize;
mem_free *= pagesize;
print mem_hw - mem_inactive - mem_cache - mem_free;
}
' "$file");
name_val "Total" $(shorten ${mem_hw} 1)
name_val "Virtual" $(shorten ${physical} 1)
name_val "Used" $(shorten ${mem_used} 1)
}
parse_memory_sysctl_netbsd() { local PTFUNCNAME=parse_memory_sysctl_netbsd;
local file="$1"
local swapctl_file="$2"
[ -e "$file" -a -e "$swapctl_file" ] || return
local swap_mem="$(awk '{print $2*512}' "$swapctl_file")"
name_val "Total" $(shorten "$(awk '/hw.physmem /{print $NF}' "$file")" 1)
name_val "User" $(shorten "$(awk '/hw.usermem /{print $NF}' "$file")" 1)
name_val "Swap" $(shorten ${swap_mem} 1)
}
parse_memory_sysctl_openbsd() { local PTFUNCNAME=parse_memory_sysctl_openbsd;
local file="$1"
local swapctl_file="$2"
[ -e "$file" -a -e "$swapctl_file" ] || return
local swap_mem="$(awk '{print $2*512}' "$swapctl_file")"
name_val "Total" $(shorten "$(awk -F= '/hw.physmem/{print $2}' "$file")" 1)
name_val "User" $(shorten "$(awk -F= '/hw.usermem/{print $2}' "$file")" 1)
name_val "Swap" $(shorten ${swap_mem} 1)
}
parse_dmidecode_mem_devices () { local PTFUNCNAME=parse_dmidecode_mem_devices;
local file="$1"
[ -e "$file" ] || return
echo " Locator Size Speed Form Factor Type Type Detail"
echo " ========= ======== ================= ============= ============= ==========="
sed -e '/./{H;$!d;}' \
-e 'x;/Memory Device\n/!d;' \
-e 's/: /:/g' \
-e 's/</{/g' \
-e 's/>/}/g' \
-e 's/[ \t]*\n/\n/g' \
"${file}" \
| awk -F: '/Size|Type|Form.Factor|Type.Detail|^[\t ]+Locator/{printf("|%s", $2)}/^[\t ]+Speed/{print "|" $2}' \
| sed -e 's/No Module Installed/{EMPTY}/' \
| sort \
| awk -F'|' '{printf(" %-9s %-8s %-17s %-13s %-13s %-8s\n", $4, $2, $7, $3, $5, $6);}'
}
parse_ip_s_link () { local PTFUNCNAME=parse_ip_s_link;
local file="$1"
[ -e "$file" ] || return
echo " interface rx_bytes rx_packets rx_errors tx_bytes tx_packets tx_errors"
echo " ========= ========= ========== ========== ========== ========== =========="
awk "/^[1-9][0-9]*:/ {
save[\"iface\"] = substr(\$2, 1, index(\$2, \":\") - 1);
new = 1;
}
\$0 !~ /[^0-9 ]/ {
if ( new == 1 ) {
new = 0;
fuzzy_var = \$1; ${fuzzy_formula} save[\"bytes\"] = fuzzy_var;
fuzzy_var = \$2; ${fuzzy_formula} save[\"packs\"] = fuzzy_var;
fuzzy_var = \$3; ${fuzzy_formula} save[\"errs\"] = fuzzy_var;
}
else {
fuzzy_var = \$1; ${fuzzy_formula} tx_bytes = fuzzy_var;
fuzzy_var = \$2; ${fuzzy_formula} tx_packets = fuzzy_var;
fuzzy_var = \$3; ${fuzzy_formula} tx_errors = fuzzy_var;
printf \" %-8s %10.0f %10.0f %10.0f %10.0f %10.0f %10.0f\\n\", save[\"iface\"], save[\"bytes\"], save[\"packs\"], save[\"errs\"], tx_bytes, tx_packets, tx_errors;
}
}" "$file"
}
parse_ethtool () {
local file="$1"
[ -e "$file" ] || return
echo " Device Speed Duplex"
echo " ========= ========= ========="
awk '
/^Settings for / {
device = substr($3, 1, index($3, ":") ? index($3, ":")-1 : length($3));
device_names[device] = device;
}
/Speed:/ { devices[device ",speed"] = $2 }
/Duplex:/ { devices[device ",duplex"] = $2 }
END {
for ( device in device_names ) {
printf(" %-10s %-10s %-10s\n",
device,
devices[device ",speed"],
devices[device ",duplex"]);
}
}
' "$file"
}
parse_netstat () { local PTFUNCNAME=parse_netstat;
local file="$1"
[ -e "$file" ] || return
echo " Connections from remote IP addresses"
awk '$1 ~ /^tcp/ && $5 ~ /^[1-9]/ {
print substr($5, 1, index($5, ":") - 1);
}' "${file}" | sort | uniq -c \
| awk "{
fuzzy_var=\$1;
${fuzzy_formula}
printf \" %-15s %5d\\n\", \$2, fuzzy_var;
}" \
| sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4
echo " Connections to local IP addresses"
awk '$1 ~ /^tcp/ && $5 ~ /^[1-9]/ {
print substr($4, 1, index($4, ":") - 1);
}' "${file}" | sort | uniq -c \
| awk "{
fuzzy_var=\$1;
${fuzzy_formula}
printf \" %-15s %5d\\n\", \$2, fuzzy_var;
}" \
| sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4
echo " Connections to top 10 local ports"
awk '$1 ~ /^tcp/ && $5 ~ /^[1-9]/ {
print substr($4, index($4, ":") + 1);
}' "${file}" | sort | uniq -c | sort -rn | head -n10 \
| awk "{
fuzzy_var=\$1;
${fuzzy_formula}
printf \" %-15s %5d\\n\", \$2, fuzzy_var;
}" | sort
echo " States of connections"
awk '$1 ~ /^tcp/ {
print $6;
}' "${file}" | sort | uniq -c | sort -rn \
| awk "{
fuzzy_var=\$1;
${fuzzy_formula}
printf \" %-15s %5d\\n\", \$2, fuzzy_var;
}" | sort
}
parse_filesystems () { local PTFUNCNAME=parse_filesystems;
local file="$1"
local platform="$2"
[ -e "$file" ] || return
local spec="$(awk "
BEGIN {
device = 10;
fstype = 4;
options = 4;
}
/./ {
f_device = \$1;
f_fstype = \$10;
f_options = substr(\$11, 2, length(\$11) - 2);
if ( \"$2\" ~ /(Free|Open|Net)BSD/ ) {
f_fstype = substr(\$9, 2, length(\$9) - 2);
f_options = substr(\$0, index(\$0, \",\") + 2);
f_options = substr(f_options, 1, length(f_options) - 1);
}
if ( length(f_device) > device ) {
device=length(f_device);
}
if ( length(f_fstype) > fstype ) {
fstype=length(f_fstype);
}
if ( length(f_options) > options ) {
options=length(f_options);
}
}
END{
print \"%-\" device \"s %5s %4s %-\" fstype \"s %-\" options \"s %s\";
}
" "${file}")"
awk "
BEGIN {
spec=\" ${spec}\\n\";
printf spec, \"Filesystem\", \"Size\", \"Used\", \"Type\", \"Opts\", \"Mountpoint\";
}
{
f_fstype = \$10;
f_options = substr(\$11, 2, length(\$11) - 2);
if ( \"$2\" ~ /(Free|Open|Net)BSD/ ) {
f_fstype = substr(\$9, 2, length(\$9) - 2);
f_options = substr(\$0, index(\$0, \",\") + 2);
f_options = substr(f_options, 1, length(f_options) - 1);
}
printf spec, \$1, \$2, \$5, f_fstype, f_options, \$6;
}
" "${file}"
}
parse_fdisk () { local PTFUNCNAME=parse_fdisk;
local file="$1"
[ -e "$file" -a -s "$file" ] || return
awk '
BEGIN {
format="%-12s %4s %10s %10s %18s\n";
printf(format, "Device", "Type", "Start", "End", "Size");
printf(format, "============", "====", "==========", "==========", "==================");
}
/Disk.*bytes/ {
disk = substr($2, 1, length($2) - 1);
size = $5;
printf(format, disk, "Disk", "", "", size);
}
/Units/ {
units = $9;
}
/^\/dev/ {
if ( $2 == "*" ) {
start = $3;
end = $4;
}
else {
start = $2;
end = $3;
}
printf(format, $1, "Part", start, end, sprintf("%.0f", (end - start) * units));
}
' "${file}"
}
parse_ethernet_controller_lspci () { local PTFUNCNAME=parse_ethernet_controller_lspci;
local file="$1"
[ -e "$file" ] || return
grep -i ethernet "${file}" | cut -d: -f3 | while read line; do
name_val "Controller" "${line}"
done
}
parse_hpacucli () { local PTFUNCNAME=parse_hpacucli;
local file="$1"
[ -e "$file" ] || return
grep 'logicaldrive\|physicaldrive' "${file}"
}
parse_arcconf () { local PTFUNCNAME=parse_arcconf;
local file="$1"
[ -e "$file" ] || return
local model="$(awk -F: '/Controller Model/{print $2}' "${file}")"
local chan="$(awk -F: '/Channel description/{print $2}' "${file}")"
local cache="$(awk -F: '/Installed memory/{print $2}' "${file}")"
local status="$(awk -F: '/Controller Status/{print $2}' "${file}")"
name_val "Specs" "$(echo "$model" | sed -e 's/ //'),${chan},${cache} cache,${status}"
local battery=""
if grep -q "ZMM" "$file"; then
battery="$(grep -A2 'Controller ZMM Information' "$file" \
| awk '/Status/ {s=$4}
END {printf "ZMM %s", s}')"
else
battery="$(grep -A5 'Controller Battery Info' "${file}" \
| awk '/Capacity remaining/ {c=$4}
/Status/ {s=$3}
/Time remaining/ {t=sprintf("%dd%dh%dm", $7, $9, $11)}
END {printf("%d%%, %s remaining, %s", c, t, s)}')"
fi
name_val "Battery" "${battery}"
echo
echo " LogicalDev Size RAID Disks Stripe Status Cache"
echo " ========== ========= ==== ===== ====== ======= ======="
for dev in $(awk '/Logical device number/{print $4}' "${file}"); do
sed -n -e "/^Logical device .* ${dev}$/,/^$\|^Logical device number/p" "${file}" \
| awk '
/Logical device name/ {d=$5}
/Size/ {z=$3 " " $4}
/RAID level/ {r=$4}
/Group [0-9]/ {g++}
/Stripe-unit size/ {p=$4 " " $5}
/Status of logical/ {s=$6}
/Write-cache mode.*Ena.*write-back/ {c="On (WB)"}
/Write-cache mode.*Ena.*write-thro/ {c="On (WT)"}
/Write-cache mode.*Disabled/ {c="Off"}
END {
printf(" %-10s %-9s %4d %5d %-6s %-7s %-7s\n",
d, z, r, g, p, s, c);
}'
done
echo
echo " PhysiclDev State Speed Vendor Model Size Cache"
echo " ========== ======= ============= ======= ============ =========== ======="
local tempresult=""
sed -n -e '/Physical Device information/,/^$/p' "${file}" \
| awk -F: '
/Device #[0-9]/ {
device=substr($0, index($0, "#"));
devicenames[device]=device;
}
/Device is a/ {
devices[device ",isa"] = substr($0, index($0, "is a") + 5);
}
/State/ {
devices[device ",state"] = substr($2, 2);
}
/Transfer Speed/ {
devices[device ",speed"] = substr($2, 2);
}
/Vendor/ {
devices[device ",vendor"] = substr($2, 2);
}
/Model/ {
devices[device ",model"] = substr($2, 2);
}
/Size/ {
devices[device ",size"] = substr($2, 2);
}
/Write Cache/ {
if ( $2 ~ /Enabled .write-back./ )
devices[device ",cache"] = "On (WB)";
else
if ( $2 ~ /Enabled .write-th/ )
devices[device ",cache"] = "On (WT)";
else
devices[device ",cache"] = "Off";
}
END {
for ( device in devicenames ) {
if ( devices[device ",isa"] ~ /Hard drive/ ) {
printf(" %-10s %-7s %-13s %-7s %-12s %-11s %-7s\n",
devices[device ",isa"],
devices[device ",state"],
devices[device ",speed"],
devices[device ",vendor"],
devices[device ",model"],
devices[device ",size"],
devices[device ",cache"]);
}
}
}'
}
parse_fusionmpt_lsiutil () { local PTFUNCNAME=parse_fusionmpt_lsiutil;
local file="$1"
echo
awk '/LSI.*Firmware/ { print " ", $0 }' "${file}"
grep . "${file}" | sed -n -e '/B___T___L/,$ {s/^/ /; p}'
}
parse_lsi_megaraid_adapter_info () { local PTFUNCNAME=parse_lsi_megaraid_adapter_info;
local file="$1"
[ -e "$file" ] || return
local name="$(awk -F: '/Product Name/{print substr($2, 2)}' "${file}")";
local int=$(awk '/Host Interface/{print $4}' "${file}");
local prt=$(awk '/Number of Backend Port/{print $5}' "${file}");
local bbu=$(awk '/^BBU :/{print $3}' "${file}");
local mem=$(awk '/Memory Size/{print $4}' "${file}");
local vdr=$(awk '/Virtual Drives/{print $4}' "${file}");
local dvd=$(awk '/Degraded/{print $3}' "${file}");
local phy=$(awk '/^ Disks/{print $3}' "${file}");
local crd=$(awk '/Critical Disks/{print $4}' "${file}");
local fad=$(awk '/Failed Disks/{print $4}' "${file}");
name_val "Model" "${name}, ${int} interface, ${prt} ports"
name_val "Cache" "${mem} Memory, BBU ${bbu}"
}
parse_lsi_megaraid_bbu_status () { local PTFUNCNAME=parse_lsi_megaraid_bbu_status;
local file="$1"
[ -e "$file" ] || return
local charge=$(awk '/Relative State/{print $5}' "${file}");
local temp=$(awk '/^Temperature/{print $2}' "${file}");
local soh=$(awk '/isSOHGood:/{print $2}' "${file}");
name_val "BBU" "${charge}% Charged, Temperature ${temp}C, isSOHGood=${soh}"
}
format_lvs () { local PTFUNCNAME=format_lvs;
local file="$1"
if [ -e "$file" ]; then
grep -v "open failed" "$file"
else
echo "Unable to collect information";
fi
}
parse_lsi_megaraid_devices () { local PTFUNCNAME=parse_lsi_megaraid_devices;
local file="$1"
[ -e "$file" ] || return
echo
echo " PhysiclDev Type State Errors Vendor Model Size"
echo " ========== ==== ======= ====== ======= ============ ==========="
for dev in $(awk '/Device Id/{print $3}' "${file}"); do
sed -e '/./{H;$!d;}' -e "x;/Device Id: ${dev}/!d;" "${file}" \
| awk '
/Media Type/ {d=substr($0, index($0, ":") + 2)}
/PD Type/ {t=$3}
/Firmware state/ {s=$3}
/Media Error Count/ {me=$4}
/Other Error Count/ {oe=$4}
/Predictive Failure Count/ {pe=$4}
/Inquiry Data/ {v=$3; m=$4;}
/Raw Size/ {z=$3}
END {
printf(" %-10s %-4s %-7s %6s %-7s %-12s %-7s\n",
substr(d, 1, 10), t, s, me "/" oe "/" pe, v, m, z);
}'
done
}
parse_lsi_megaraid_virtual_devices () { local PTFUNCNAME=parse_lsi_megaraid_virtual_devices;
local file="$1"
[ -e "$file" ] || return
echo
echo " VirtualDev Size RAID Level Disks SpnDpth Stripe Status Cache"
echo " ========== ========= ========== ===== ======= ====== ======= ========="
awk '
/^Virtual (Drive|Disk):/ {
device = $3;
devicenames[device] = device;
}
/Number Of Drives/ {
devices[device ",numdisks"] = substr($0, index($0, ":") + 1);
}
/^Name/ {
devices[device ",name"] = substr($0, index($0, ":") + 1) > "" ? substr($0, index($0, ":") + 1) : "(no name)";
}
/RAID Level/ {
devices[device ",primary"] = substr($3, index($3, "-") + 1, 1);
devices[device ",secondary"] = substr($4, index($4, "-") + 1, 1);
devices[device ",qualifier"] = substr($NF, index($NF, "-") + 1, 1);
}
/Span Depth/ {
devices[device ",spandepth"] = substr($2, index($2, ":") + 1);
}
/Number of Spans/ {
devices[device ",numspans"] = $4;
}
/^Size/ {
devices[device ",size"] = substr($0, index($0, ":") + 1);
}
/^State/ {
devices[device ",state"] = substr($0, index($0, ":") + 2);
}
/^Stripe? Size/ {
devices[device ",stripe"] = substr($0, index($0, ":") + 1);
}
/^Current Cache Policy/ {
devices[device ",wpolicy"] = $4 ~ /WriteBack/ ? "WB" : "WT";
devices[device ",rpolicy"] = $5 ~ /ReadAheadNone/ ? "no RA" : "RA";
}
END {
for ( device in devicenames ) {
raid = 0;
if ( devices[device ",primary"] == 1 ) {
raid = 1;
if ( devices[device ",secondary"] == 3 ) {
raid = 10;
}
}
else {
if ( devices[device ",primary"] == 5 ) {
raid = 5;
}
}
printf(" %-10s %-9s %-10s %5d %7s %6s %-7s %s\n",
device devices[device ",name"],
devices[device ",size"],
raid " (" devices[device ",primary"] "-" devices[device ",secondary"] "-" devices[device ",qualifier"] ")",
devices[device ",numdisks"],
devices[device ",spandepth"] "-" devices[device ",numspans"],
devices[device ",stripe"], devices[device ",state"],
devices[device ",wpolicy"] ", " devices[device ",rpolicy"]);
}
}' "${file}"
}
format_vmstat () { local PTFUNCNAME=format_vmstat;
local file="$1"
[ -e "$file" ] || return
awk "
BEGIN {
format = \" %2s %2s %4s %4s %5s %5s %6s %6s %3s %3s %3s %3s %3s\n\";
}
/procs/ {
print \" procs ---swap-- -----io---- ---system---- --------cpu--------\";
}
/bo/ {
printf format, \"r\", \"b\", \"si\", \"so\", \"bi\", \"bo\", \"ir\", \"cs\", \"us\", \"sy\", \"il\", \"wa\", \"st\";
}
\$0 !~ /r/ {
fuzzy_var = \$1; ${fuzzy_formula} r = fuzzy_var;
fuzzy_var = \$2; ${fuzzy_formula} b = fuzzy_var;
fuzzy_var = \$7; ${fuzzy_formula} si = fuzzy_var;
fuzzy_var = \$8; ${fuzzy_formula} so = fuzzy_var;
fuzzy_var = \$9; ${fuzzy_formula} bi = fuzzy_var;
fuzzy_var = \$10; ${fuzzy_formula} bo = fuzzy_var;
fuzzy_var = \$11; ${fuzzy_formula} ir = fuzzy_var;
fuzzy_var = \$12; ${fuzzy_formula} cs = fuzzy_var;
fuzzy_var = \$13; us = fuzzy_var;
fuzzy_var = \$14; sy = fuzzy_var;
fuzzy_var = \$15; il = fuzzy_var;
fuzzy_var = \$16; wa = fuzzy_var;
fuzzy_var = \$17; st = fuzzy_var;
printf format, r, b, si, so, bi, bo, ir, cs, us, sy, il, wa, st;
}
" "${file}"
}
processes_section () { local PTFUNCNAME=processes_section;
local top_process_file="$1"
local notable_procs_file="$2"
local vmstat_file="$3"
local platform="$4"
section "Top Processes"
cat "$top_process_file"
section "Notable Processes"
cat "$notable_procs_file"
if [ -e "$vmstat_file" ]; then
section "Simplified and fuzzy rounded vmstat (wait please)"
wait # For the process we forked that was gathering vmstat samples
if [ "${platform}" = "Linux" ]; then
format_vmstat "$vmstat_file"
else
cat "$vmstat_file"
fi
fi
}
section_Processor () {
local platform="$1"
local data_dir="$2"
section "Processor"
if [ -e "$data_dir/proc_cpuinfo_copy" ]; then
parse_proc_cpuinfo "$data_dir/proc_cpuinfo_copy"
elif [ "${platform}" = "FreeBSD" ]; then
parse_sysctl_cpu_freebsd "$data_dir/sysctl"
elif [ "${platform}" = "NetBSD" ]; then
parse_sysctl_cpu_netbsd "$data_dir/sysctl"
elif [ "${platform}" = "OpenBSD" ]; then
parse_sysctl_cpu_openbsd "$data_dir/sysctl"
elif [ "${platform}" = "SunOS" ]; then
parse_psrinfo_cpus "$data_dir/psrinfo_minus_v"
fi
}
section_Memory () {
local platform="$1"
local data_dir="$2"
section "Memory"
if [ "${platform}" = "Linux" ]; then
parse_free_minus_b "$data_dir/memory"
elif [ "${platform}" = "FreeBSD" ]; then
parse_memory_sysctl_freebsd "$data_dir/sysctl"
elif [ "${platform}" = "NetBSD" ]; then
parse_memory_sysctl_netbsd "$data_dir/sysctl" "$data_dir/swapctl"
elif [ "${platform}" = "OpenBSD" ]; then
parse_memory_sysctl_openbsd "$data_dir/sysctl" "$data_dir/swapctl"
elif [ "${platform}" = "SunOS" ]; then
name_val "Memory" "$(cat "$data_dir/memory")"
fi
local rss=$( get_var "rss" "$data_dir/summary" )
name_val "UsedRSS" "$(shorten ${rss} 1)"
if [ "${platform}" = "Linux" ]; then
name_val "Swappiness" "$(get_var "swappiness" "$data_dir/summary")"
name_val "DirtyPolicy" "$(get_var "dirtypolicy" "$data_dir/summary")"
local dirty_status="$(get_var "dirtystatus" "$data_dir/summary")"
if [ -n "$dirty_status" ]; then
name_val "DirtyStatus" "$dirty_status"
fi
fi
if [ -s "$data_dir/dmidecode" ]; then
parse_dmidecode_mem_devices "$data_dir/dmidecode"
fi
}
parse_uptime () {
local file="$1"
awk ' / up / {
printf substr($0, index($0, " up ")+4 );
}
!/ up / {
printf $0;
}
' "$file"
}
report_fio_minus_a () {
local file="$1"
name_val "fio Driver" "$(get_var driver_version "$file")"
local adapters="$( get_var "adapters" "$file" )"
for adapter in $( echo $adapters | awk '{for (i=1; i<=NF; i++) print $i;}' ); do
local adapter_for_output="$(echo "$adapter" | sed 's/::[0-9]*$//' | tr ':' ' ')"
name_val "$adapter_for_output" "$(get_var "${adapter}_general" "$file")"
local modules="$(get_var "${adapter}_modules" "$file")"
for module in $( echo $modules | awk '{for (i=1; i<=NF; i++) print $i;}' ); do
local name_val_len_orig=$NAME_VAL_LEN;
local NAME_VAL_LEN=16
name_val "$module" "$(get_var "${adapter}_${module}_attached_as" "$file")"
name_val "" "$(get_var "${adapter}_${module}_general" "$file")"
name_val "" "$(get_var "${adapter}_${module}_firmware" "$file")"
name_val "" "$(get_var "${adapter}_${module}_temperature" "$file")"
name_val "" "$(get_var "${adapter}_${module}_media_status" "$file")"
if [ "$(get_var "${adapter}_${module}_rated_pbw" "$file")" ]; then
name_val "" "$(get_var "${adapter}_${module}_rated_pbw" "$file")"
fi
local NAME_VAL_LEN=$name_val_len_orig;
done
done
}
report_system_summary () { local PTFUNCNAME=report_system_summary;
local data_dir="$1"
section "Percona Toolkit System Summary Report"
[ -e "$data_dir/summary" ] \
|| die "The data directory doesn't have a summary file, exiting."
local platform="$(get_var "platform" "$data_dir/summary")"
name_val "Date" "`date -u +'%F %T UTC'` (local TZ: `date +'%Z %z'`)"
name_val "Hostname" "$(get_var hostname "$data_dir/summary")"
name_val "Uptime" "$(parse_uptime "$data_dir/uptime")"
if [ "$(get_var "vendor" "$data_dir/summary")" ]; then
name_val "System" "$(get_var "system" "$data_dir/summary")";
name_val "Service Tag" "$(get_var "servicetag" "$data_dir/summary")";
fi
name_val "Platform" "${platform}"
local zonename="$(get_var zonename "$data_dir/summary")";
[ -n "${zonename}" ] && name_val "Zonename" "$zonename"
name_val "Release" "$(get_var "release" "$data_dir/summary")"
name_val "Kernel" "$(get_var "kernel" "$data_dir/summary")"
name_val "Architecture" "CPU = $(get_var "CPU_ARCH" "$data_dir/summary"), OS = $(get_var "OS_ARCH" "$data_dir/summary")"
local threading="$(get_var threading "$data_dir/summary")"
local compiler="$(get_var compiler "$data_dir/summary")"
[ -n "$threading" ] && name_val "Threading" "$threading"
[ -n "$compiler" ] && name_val "Compiler" "$compiler"
local getenforce="$(get_var getenforce "$data_dir/summary")"
[ -n "$getenforce" ] && name_val "SELinux" "${getenforce}";
name_val "Virtualized" "$(get_var "virt" "$data_dir/summary")"
section_Processor "$platform" "$data_dir"
section_Memory "$platform" "$data_dir"
if [ -s "$data_dir/fusion-io_card" ]; then
section "Fusion-io Card"
report_fio_minus_a "$data_dir/fusion-io_card"
fi
if [ -s "$data_dir/mounted_fs" ]; then
section "Mounted Filesystems"
parse_filesystems "$data_dir/mounted_fs" "${platform}"
fi
if [ "${platform}" = "Linux" ]; then
section "Disk Schedulers And Queue Size"
local disks="$( get_var "internal::disks" "$data_dir/summary" )"
for disk in $disks; do
local scheduler="$( get_var "internal::${disk}" "$data_dir/summary" )"
name_val "${disk}" "${scheduler:-"UNREADABLE"}"
done
section "Disk Partioning"
parse_fdisk "$data_dir/partitioning"
section "Kernel Inode State"
for file in dentry-state file-nr inode-nr; do
name_val "${file}" "$(get_var "${file}" "$data_dir/summary")"
done
section "LVM Volumes"
format_lvs "$data_dir/lvs"
section "LVM Volume Groups"
format_lvs "$data_dir/vgs"
fi
section "RAID Controller"
local controller="$(get_var "raid_controller" "$data_dir/summary")"
name_val "Controller" "$controller"
local key="$(get_var "internal::raid_opt" "$data_dir/summary")"
case "$key" in
0)
cat "$data_dir/raid-controller"
;;
1)
parse_arcconf "$data_dir/raid-controller"
;;
2)
parse_hpacucli "$data_dir/raid-controller"
;;
3)
[ -e "$data_dir/lsi_megaraid_adapter_info.tmp" ] && \
parse_lsi_megaraid_adapter_info "$data_dir/lsi_megaraid_adapter_info.tmp"
[ -e "$data_dir/lsi_megaraid_bbu_status.tmp" ] && \
parse_lsi_megaraid_bbu_status "$data_dir/lsi_megaraid_bbu_status.tmp"
if [ -e "$data_dir/lsi_megaraid_devices.tmp" ]; then
parse_lsi_megaraid_virtual_devices "$data_dir/lsi_megaraid_devices.tmp"
parse_lsi_megaraid_devices "$data_dir/lsi_megaraid_devices.tmp"
fi
;;
esac
if [ "${OPT_SUMMARIZE_NETWORK}" ]; then
if [ "${platform}" = "Linux" ]; then
section "Network Config"
if [ -s "$data_dir/lspci_file" ]; then
parse_ethernet_controller_lspci "$data_dir/lspci_file"
fi
if grep "net.ipv4.tcp_fin_timeout" "$data_dir/sysctl" > /dev/null 2>&1; then
name_val "FIN Timeout" "$(awk '/net.ipv4.tcp_fin_timeout/{print $NF}' "$data_dir/sysctl")"
name_val "Port Range" "$(awk '/net.ipv4.ip_local_port_range/{print $NF}' "$data_dir/sysctl")"
fi
fi
if [ -s "$data_dir/ip" ]; then
section "Interface Statistics"
parse_ip_s_link "$data_dir/ip"
fi
if [ -s "$data_dir/network_devices" ]; then
section "Network Devices"
parse_ethtool "$data_dir/network_devices"
fi
if [ "${platform}" = "Linux" -a -e "$data_dir/netstat" ]; then
section "Network Connections"
parse_netstat "$data_dir/netstat"
fi
fi
[ "$OPT_SUMMARIZE_PROCESSES" ] && processes_section \
"$data_dir/processes" \
"$data_dir/notable_procs" \
"$data_dir/vmstat" \
"$platform"
section "The End"
}
# ###########################################################################
# End report_system_info package
# ###########################################################################
# ##############################################################################
# The main() function is called at the end of the script. This makes it
# testable. Major bits of parsing are separated into functions for testability.
# ##############################################################################
main () { local PTFUNCNAME=main;
trap sigtrap HUP INT TERM
local RAN_WITH="--sleep=$OPT_SLEEP --save-samples=$OPT_SAVE_SAMPLES --read-samples=$OPT_READ_SAMPLES"
# Begin by setting the $PATH to include some common locations that are not
# always in the $PATH, including the "sbin" locations, and some common
# locations for proprietary management software, such as RAID controllers.
export PATH="${PATH}:/usr/local/bin:/usr/bin:/bin:/usr/libexec"
export PATH="${PATH}:/usr/local/sbin:/usr/sbin:/sbin"
export PATH="${PATH}:/usr/StorMan/:/opt/MegaRAID/MegaCli/"
setup_commands
_d "Starting $0 $RAN_WITH"
# Set up temporary files.
mk_tmpdir
local data_dir="$(setup_data_dir "${OPT_SAVE_SAMPLES:-""}")"
if [ -n "$OPT_READ_SAMPLES" -a -d "$OPT_READ_SAMPLES" ]; then
data_dir="$OPT_READ_SAMPLES"
else
collect_system_data "$data_dir" 2>"$data_dir/collect.err"
fi
report_system_summary "$data_dir"
rm_tmpdir
}
sigtrap() { local PTFUNCNAME=sigtrap;
warn "Caught signal, forcing exit"
rm_tmpdir
exit $EXIT_STATUS
}
# Execute the program if it was not included from another file. This makes it
# possible to include without executing, and thus test.
if [ "${0##*/}" = "$TOOL" ] \
|| [ "${0##*/}" = "bash" -a "${_:-""}" = "$0" ]; then
# Set up temporary dir.
mk_tmpdir
# Parse command line options.
parse_options "$0" "${@:-""}"
usage_or_errors "$0"
po_status=$?
rm_tmpdir
if [ $po_status -ne 0 ]; then
exit $po_status
fi
main "${@:-""}"
fi
# ############################################################################
# Documentation
# ############################################################################
:<<'DOCUMENTATION'
=pod
=head1 NAME
pt-summary - Summarize system information nicely.
=head1 SYNOPSIS
Usage: pt-summary
pt-summary conveniently summarizes the status and configuration of a server.
It is not a tuning tool or diagnosis tool. It produces a report that is easy
to diff and can be pasted into emails without losing the formatting. This
tool works well on many types of Unix systems.
Download and run:
wget http://percona.com/get/pt-summary
bash ./pt-summary
=head1 RISKS
Percona Toolkit is mature, proven in the real world, and well tested,
but all database tools can pose a risk to the system and the database
server. Before using this tool, please:
=over
=item * Read the tool's documentation
=item * Review the tool's known L<"BUGS">
=item * Test the tool on a non-production server
=item * Backup your production server and verify the backups
=back
=head1 DESCRIPTION
pt-summary runs a large variety of commands to inspect system status and
configuration, saves the output into files in a temporary directory, and
then runs Unix commands on these results to format them nicely. It works
best when executed as a privileged user, but will also work without privileges,
although some output might not be possible to generate without root.
=head1 OUTPUT
Many of the outputs from this tool are deliberately rounded to show their
magnitude but not the exact detail. This is called fuzzy-rounding. The idea is
that it doesn't matter whether a particular counter is 918 or 921; such a small
variation is insignificant, and only makes the output hard to compare to other
servers. Fuzzy-rounding rounds in larger increments as the input grows. It
begins by rounding to the nearest 5, then the nearest 10, nearest 25, and then
repeats by a factor of 10 larger (50, 100, 250), and so on, as the input grows.
The following is a simple report generated from a CentOS virtual machine,
broken into sections with commentary following each section. Some long lines
are reformatted for clarity when reading this documentation as a manual page in
a terminal.
# Percona Toolkit System Summary Report ######################
Date | 2012-03-30 00:58:07 UTC (local TZ: EDT -0400)
Hostname | localhost.localdomain
Uptime | 20:58:06 up 1 day, 20 min, 1 user,
load average: 0.14, 0.18, 0.18
System | innotek GmbH; VirtualBox; v1.2 ()
Service Tag | 0
Platform | Linux
Release | CentOS release 5.5 (Final)
Kernel | 2.6.18-194.el5
Architecture | CPU = 32-bit, OS = 32-bit
Threading | NPTL 2.5
Compiler | GNU CC version 4.1.2 20080704 (Red Hat 4.1.2-48).
SELinux | Enforcing
Virtualized | VirtualBox
This section shows the current date and time, and a synopsis of the server and
operating system.
# Processor ##################################################
Processors | physical = 1, cores = 0, virtual = 1, hyperthreading = no
Speeds | 1x2510.626
Models | 1xIntel(R) Core(TM) i5-2400S CPU @ 2.50GHz
Caches | 1x6144 KB
This section is derived from F</proc/cpuinfo>.
# Memory #####################################################
Total | 503.2M
Free | 29.0M
Used | physical = 474.2M, swap allocated = 1.0M,
swap used = 16.0k, virtual = 474.3M
Buffers | 33.9M
Caches | 262.6M
Dirty | 396 kB
UsedRSS | 201.9M
Swappiness | 60
DirtyPolicy | 40, 10
Locator Size Speed Form Factor Type Type Detail
======= ==== ===== =========== ==== ===========
Information about memory is gathered from C<free>. The Used statistic is the
total of the rss sizes displayed by C<ps>. The Dirty statistic for the cached
value comes from F</proc/meminfo>. On Linux, the swappiness settings are
gathered from C<sysctl>. The final portion of this section is a table of the
DIMMs, which comes from C<dmidecode>. In this example there is no output.
# Mounted Filesystems ########################################
Filesystem Size Used Type Opts Mountpoint
/dev/mapper/VolGroup00-LogVol00 15G 17% ext3 rw /
/dev/sda1 99M 13% ext3 rw /boot
tmpfs 252M 0% tmpfs rw /dev/shm
The mounted filesystem section is a combination of information from C<mount> and
C<df>. This section is skipped if you disable L<"--summarize-mounts">.
# Disk Schedulers And Queue Size #############################
dm-0 | UNREADABLE
dm-1 | UNREADABLE
hdc | [cfq] 128
md0 | UNREADABLE
sda | [cfq] 128
The disk scheduler information is extracted from the F</sys> filesystem in
Linux.
# Disk Partioning ############################################
Device Type Start End Size
============ ==== ========== ========== ==================
/dev/sda Disk 17179869184
/dev/sda1 Part 1 13 98703360
/dev/sda2 Part 14 2088 17059230720
Information about disk partitioning comes from C<fdisk -l>.
# Kernel Inode State #########################################
dentry-state | 10697 8559 45 0 0 0
file-nr | 960 0 50539
inode-nr | 14059 8139
These lines are from the files of the same name in the F</proc/sys/fs>
directory on Linux. Read the C<proc> man page to learn about the meaning of
these files on your system.
# LVM Volumes ################################################
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
LogVol00 VolGroup00 -wi-ao 269.00G
LogVol01 VolGroup00 -wi-ao 9.75G
This section shows the output of C<lvs>.
# RAID Controller ############################################
Controller | No RAID controller detected
The tool can detect a variety of RAID controllers by examining C<lspci> and
C<dmesg> information. If the controller software is installed on the system, in
many cases it is able to execute status commands and show a summary of the RAID
controller's status and configuration. If your system is not supported, please
file a bug report.
# Network Config #############################################
Controller | Intel Corporation 82540EM Gigabit Ethernet Controller
FIN Timeout | 60
Port Range | 61000
The network controllers attached to the system are detected from C<lspci>. The
TCP/IP protocol configuration parameters are extracted from C<sysctl>. You can skip this section by disabling the L<"--summarize-network"> option.
# Interface Statistics #######################################
interface rx_bytes rx_packets rx_errors tx_bytes tx_packets tx_errors
========= ======== ========== ========= ======== ========== =========
lo 60000000 12500 0 60000000 12500 0
eth0 15000000 80000 0 1500000 10000 0
sit0 0 0 0 0 0 0
Interface statistics are gathered from C<ip -s link> and are fuzzy-rounded. The
columns are received and transmitted bytes, packets, and errors. You can skip
this section by disabling the L<"--summarize-network"> option.
# Network Connections ########################################
Connections from remote IP addresses
127.0.0.1 2
Connections to local IP addresses
127.0.0.1 2
Connections to top 10 local ports
38346 1
60875 1
States of connections
ESTABLISHED 5
LISTEN 8
This section shows a summary of network connections, retrieved from C<netstat>
and "fuzzy-rounded" to make them easier to compare when the numbers grow large.
There are two sub-sections showing how many connections there are per origin
and destination IP address, and a sub-section showing the count of ports in
use. The section ends with the count of the network connections' states. You
can skip this section by disabling the L<"--summarize-network"> option.
# Top Processes ##############################################
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 15 0 2072 628 540 S 0.0 0.1 0:02.55 init
2 root RT -5 0 0 0 S 0.0 0.0 0:00.00 migration/0
3 root 34 19 0 0 0 S 0.0 0.0 0:00.03 ksoftirqd/0
4 root RT -5 0 0 0 S 0.0 0.0 0:00.00 watchdog/0
5 root 10 -5 0 0 0 S 0.0 0.0 0:00.97 events/0
6 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 khelper
7 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 kthread
10 root 10 -5 0 0 0 S 0.0 0.0 0:00.13 kblockd/0
11 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 kacpid
# Notable Processes ##########################################
PID OOM COMMAND
2028 +0 sshd
This section shows the first few lines of C<top> so that you can see what
processes are actively using CPU time. The notable processes include the SSH
daemon and any process whose out-of-memory-killer priority is set to 17. You
can skip this section by disabling the L<"--summarize-processes"> option.
# Simplified and fuzzy rounded vmstat (wait please) ##########
procs ---swap-- -----io---- ---system---- --------cpu--------
r b si so bi bo ir cs us sy il wa st
2 0 0 0 3 15 30 125 0 0 99 0 0
0 0 0 0 0 0 1250 800 6 10 84 0 0
0 0 0 0 0 0 1000 125 0 0 100 0 0
0 0 0 0 0 0 1000 125 0 0 100 0 0
0 0 0 0 0 450 1000 125 0 1 88 11 0
# The End ####################################################
This section is a trimmed-down sample of C<vmstat 1 5>, so you can see the
general status of the system at present. The values in the table are
fuzzy-rounded, except for the CPU columns. You can skip this section by
disabling the L<"--summarize-processes"> option.
=head1 OPTIONS
=over
=item --config
type: string
Read this comma-separated list of config files. If specified, this must be the
first option on the command line.
=item --help
Print help and exit.
=item --read-samples
type: string
Create a report from the files in this directory.
=item --save-samples
type: string
Save the collected data in this directory.
=item --sleep
type: int; default: 5
How long to sleep when gathering samples from vmstat.
=item --summarize-mounts
default: yes; negatable: yes
Report on mounted filesystems and disk usage.
=item --summarize-network
default: yes; negatable: yes
Report on network controllers and configuration.
=item --summarize-processes
default: yes; negatable: yes
Report on top processes and C<vmstat> output.
=item --version
Print tool's version and exit.
=back
=head1 ENVIRONMENT
This tool does not use any environment variables.
=head1 SYSTEM REQUIREMENTS
This tool requires the Bourne shell (F</bin/sh>).
=head1 BUGS
For a list of known bugs, see L<http://www.percona.com/bugs/pt-summary>.
Please report bugs at L<https://bugs.launchpad.net/percona-toolkit>.
Include the following information in your bug report:
=over
=item * Complete command-line used to run the tool
=item * Tool L<"--version">
=item * MySQL version of all servers involved
=item * Output from the tool including STDERR
=item * Input files (log/dump/config files, etc.)
=back
If possible, include debugging output by running the tool with C<PTDEBUG>;
see L<"ENVIRONMENT">.
=head1 DOWNLOADING
Visit L<http://www.percona.com/software/percona-toolkit/> to download the
latest release of Percona Toolkit. Or, get the latest release from the
command line:
wget percona.com/get/percona-toolkit.tar.gz
wget percona.com/get/percona-toolkit.rpm
wget percona.com/get/percona-toolkit.deb
You can also get individual tools from the latest release:
wget percona.com/get/TOOL
Replace C<TOOL> with the name of any tool.
=head1 AUTHORS
Baron Schwartz, Kevin van Zonneveld, and Brian Fraser
=head1 ABOUT PERCONA TOOLKIT
This tool is part of Percona Toolkit, a collection of advanced command-line
tools for MySQL developed by Percona. Percona Toolkit was forked from two
projects in June, 2011: Maatkit and Aspersa. Those projects were created by
Baron Schwartz and primarily developed by him and Daniel Nichter. Visit
L<http://www.percona.com/software/> to learn about other free, open-source
software from Percona.
=head1 COPYRIGHT, LICENSE, AND WARRANTY
This program is copyright 2011-2015 Percona LLC and/or its affiliates,
2010-2011 Baron Schwartz.
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, version 2; OR the Perl Artistic License. On UNIX and similar
systems, you can issue `man perlgpl' or `man perlartistic' to read these
licenses.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA.
=head1 VERSION
pt-summary 2.2.16
=cut
DOCUMENTATION