(temp commit, syncing up)

This commit is contained in:
Brian Fraser fraserb@gmail.com
2012-03-20 11:21:16 -03:00
parent 3cfb1c0af7
commit 31afeb73b5
14 changed files with 3624 additions and 852 deletions

View File

@@ -0,0 +1,192 @@
# This program is copyright 2011-2012 Percona Inc.
# Feedback and improvements are welcome.
#
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTIBILITY 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.
# ###########################################################################
# collect_mysql_info package
# ###########################################################################
# Package: collect_mysql_info
# collect collects mysql information.
# XXX
# THIS LIB REQUIRES log_warn_die.sh, summary_common.sh, and alt_cmds.sh!
# XXX
# Simply looks for instances of mysqld in the outof of ps.
collect_mysqld_instances () {
local file="$1"
ps auxww 2>/dev/null | grep mysqld > "$file"
}
# Tries to find the my.cnf file by examining 'ps' output.
# You have to specify the port for the instance you are
# interested in, in case there are multiple instances.
find_my_cnf_file() {
local file="$1"
local port=${2:-""}
local cnf_file=""
if test -n "$port" && grep -- "/mysqld.*--port=$port" "${file}" >/dev/null 2>&1 ; then
cnf_file="$(grep -- "/mysqld.*--port=$port" "${file}" \
| awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }' \
| head -n1)"
else
cnf_file="$(grep '/mysqld' "${file}" \
| awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }' \
| head -n1)"
fi
if [ ! -n "${cnf_file}" ]; then
_d "Cannot autodetect config file, trying common locations"
cnf_file="/etc/my.cnf";
if [ ! -e "${cnf_file}" ]; then
cnf_file="/etc/mysql/my.cnf";
fi
if [ ! -e "${cnf_file}" ]; then
cnf_file="/var/db/mysql/my.cnf";
fi
fi
echo "$cnf_file"
}
collect_mysql_variables () {
local file="$1"
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW /*!40100 GLOBAL*/ VARIABLES' > "$file"
}
collect_mysql_status () {
local file="$1"
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW /*!50000 GLOBAL*/ STATUS' > "$file"
}
collect_mysql_databases () {
local file="$1"
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW DATABASES' > "$file" 2>/dev/null
}
collect_mysql_plugins () {
local file="$1"
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW PLUGINS' > "$file" 2>/dev/null
}
collect_mysql_slave_status () {
local file="$1"
$CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW SLAVE STATUS' > "$file" 2>/dev/null
}
collect_mysql_innodb_status () {
local file="$1"
$CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW /*!50000 ENGINE*/ INNODB STATUS' > "$file" 2>/dev/null
}
collect_mysql_processlist () {
local file="$1"
$CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW FULL PROCESSLIST' > "$file" 2>/dev/null
}
collect_mysql_users () {
local file="$1"
$CMD_MYSQL $EXT_ARGV -ssE -e 'SELECT COUNT(*), SUM(user=""), SUM(password=""), SUM(password NOT LIKE "*%") FROM mysql.user' > "$file" 2>/dev/null
}
collect_master_logs_status () {
local master_logs_file="$1"
local master_status_file="$2"
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW MASTER LOGS' > "$master_logs_file" 2>/dev/null
$CMD_MYSQL $EXT_ARGV -ss -e 'SHOW MASTER STATUS' > "$master_status_file" 2>/dev/null
}
# Somewhat different from the others, this one joins the status we got earlier
collect_mysql_deferred_status () {
local status_file="$1"
local defer_file="$2"
collect_mysql_status "$TMPDIR/defer_gatherer"
cat "$TMPDIR/defer_gatherer" | join "$status_file" - > "$defer_file"
}
collect_internal_vars () {
local file="$1"
local FNV_64=""
if $CMD_MYSQL $EXT_ARGV -e 'SELECT FNV_64("a")' >/dev/null 2>&1; then
FNV_64="Enabled";
else
FNV_64="Unknown";
fi
local now="$($CMD_MYSQL $EXT_ARGV -ss -e 'SELECT NOW()')"
local user="$($CMD_MYSQL $EXT_ARGV -ss -e 'SELECT CURRENT_USER()')"
local trigger_count=$($CMD_MYSQL $EXT_ARGV -ss -e "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TRIGGERS" 2>/dev/null)
local has_symbols="$(has_symbols "${CMD_MYSQL}")"
echo "pt-summary-internal-now $now" >> "$file"
echo "pt-summary-internal-user $user" >> "$file"
echo "pt-summary-internal-FNV_64 $FNV_64" >> "$file"
echo "pt-summary-internal-trigger_count $trigger_count" >> "$file"
echo "pt-summary-internal-symbols $has_symbols" >> "$file"
}
collect_mysql_info () {
local dir="$1"
local prefix="$2"
collect_mysqld_instances "$dir/${prefix}-mysqld-instances"
collect_mysql_variables "$dir/${prefix}-mysql-variables"
collect_mysql_status "$dir/${prefix}-mysql-status"
collect_mysql_databases "$dir/${prefix}-mysql-databases"
collect_mysql_plugins "$dir/${prefix}-mysql-plugins"
collect_mysql_slave_status "$dir/${prefix}-mysql-slave"
collect_mysql_innodb_status "$dir/${prefix}-innodb-status"
collect_mysql_processlist "$dir/${prefix}-mysql-processlist"
collect_mysql_users "$dir/${prefix}-mysql-users"
local binlog="$(get_var log_bin "$dir/${prefix}-mysql-variables")"
if [ "${binlog}" ]; then
_d "Got a binlog, going to get MASTER LOGS and MASTER STATUS"
collect_master_logs_status "$dir/${prefix}-mysql-master-logs" "$dir/${prefix}-mysql-master-status"
fi
local uptime="$(get_var Uptime "$dir/${prefix}-mysql-status")"
local current_time="$($CMD_MYSQL $EXT_ARGV -ss -e \
"SELECT LEFT(NOW() - INTERVAL ${uptime} SECOND, 16)")"
local port="$(get_var port "$dir/${prefix}-mysql-variables")"
local cnf_file=$(find_my_cnf_file "$dir/${prefix}-mysqld-instances" ${port});
# TODO: Do these require a file of their own?
echo "pt-summary-internal-current_time $current_time" >> "$dir/${prefix}-mysql-variables"
echo "pt-summary-internal-Config_File $cnf_file" >> "$dir/${prefix}-mysql-variables"
collect_internal_vars "$dir/${prefix}-mysql-variables"
if [ -n "${OPT_DUMP_SCHEMAS}" ]; then
_d "--dump-schemas passed in, dumping early"
local trg_arg="$( get_mysqldump_args "$dir/${prefix}-mysql-variables" )"
get_mysqldump_for "$dir/${prefix}-mysqldump" "${trg_arg}" "${OPT_DUMP_SCHEMAS}"
fi
# TODO: gather this data in the same format as normal: TS line, stats
(
sleep $OPT_SLEEP
collect_mysql_deferred_status "$dir/${prefix}-mysql-status" "$dir/${prefix}-mysql-status-defer"
) &
_d "Forked child is $!"
}
# ###########################################################################
# End collect_mysql_info package
# ###########################################################################

View File

@@ -0,0 +1,456 @@
# This program is copyright 2011-2012 Percona Inc.
# Feedback and improvements are welcome.
#
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTIBILITY 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.
# ###########################################################################
# collect_system_info package
# ###########################################################################
# Package: collect_system_info
# collects system information.
# XXX
# THIS LIB REQUIRES log_warn_die.sh, summary_common.sh, and alt_cmds.sh!
# XXX
# While extremely unwieldly, this allows us to fake the commands when testing.
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_TOP="$(_which top 2>/dev/null)"
CMD_VMSTAT="$(_which vmstat 2>/dev/null)"
CMD_IP="$( _which ip 2>/dev/null )"
CMD_NETSTAT="$( _which netstat 2>/dev/null )"
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
# ########################################################################
# Grab a bunch of stuff and put it into temp files for later.
# ########################################################################
$CMD_SYSCTL -a > "$data_dir/sysctl" 2>/dev/null
if [ -n "${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"
echo "uptime $(uptime | awk '{print substr($0, index($0, "up") + 3)}')" >> "$data_dir/summary"
processor_info "$data_dir"
find_release_and_kernel "$data_dir/summary" "$platform"
cpu_and_os_arch "$data_dir/summary" "$platform"
find_virtualization "$data_dir/summary" "$platform" "$data_dir/dmesg_file" "$data_dir/lspci_file"
dmidecode_system_info "$data_dir/summary"
if [ "${platform}" = "SunOS" ]; then
if [ -n "${CMD_ZONENAME}" ]; then
echo "zonename $($CMD_ZONENAME)" >> "$data_dir/summary"
fi
fi
# Threading library
if [ "${platform}" = "Linux" ]; then
echo "threading $(getconf GNU_LIBPTHREAD_VERSION)" >> "$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
if [ "${platform}" = "Linux" ]; then
local getenforce=""
if [ -n "$CMD_GETENFORCE" ]; then
getenforce="$($CMD_GETENFORCE 2>&1)";
fi
echo "getenforce ${getenforce:-No SELinux detected}" >> "$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"
if [ "${platform}" = "Linux" ]; then
echo "swappiness $(awk '/vm.swappiness/{print $3}' "$data_dir/sysctl")">> "$data_dir/summary"
echo "dirtypolicy $(awk '/vm.dirty_ratio/{print $3}' "$data_dir/sysctl"), $(awk '/vm.dirty_background_ratio/{print $3}' "$data_dir/sysctl")" >> "$data_dir/summary"
if $(awk '/vm.dirty_bytes/{print $3}' "$data_dir/sysctl") > /dev/null 2>&1; 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
if [ -n "$CMD_DMIDECODE" ]; then
$CMD_DMIDECODE > "$data_dir/dmidecode" 2>/dev/null
fi
find_memory_stats "$data_dir/memory" "$platform"
mounted_fs_info "$data_dir/mounted_fs" "$platform" "$PT_SUMMARY_SKIP"
raid_controller "$data_dir/summary" "$data_dir/dmesg_file" "$data_dir/lspci_file"
local controller="$(get_var raid_controller "$data_dir/summary")"
propietary_raid_controller "$data_dir/raid-controller" "$data_dir/summary" "$data_dir" "$controller"
if [ "${platform}" = "Linux" ]; then
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
if [ -n "$CMD_LVS" ] && test -x "$CMD_LVS"; then
$CMD_LVS 1>"$data_dir/lvs" 2>&1
fi
if [ -n "$CMD_VGS" ] && test -x "$CMD_VGS"; then
$CMD_VGS -o vg_name,vg_size,vg_free 2>/dev/null > "$data_dir/vgs"
fi
if [ -n "$CMD_NETSTAT" ] && echo "${PT_SUMMARY_SKIP}" | grep -v NETWORK >/dev/null; then
$CMD_NETSTAT -antp > "$data_dir/netstat" 2>/dev/null
fi
fi
if [ -n "$CMD_IP" ] && echo "${PT_SUMMARY_SKIP}" | grep -v NETWORK >/dev/null; then
$CMD_IP -s link > "$data_dir/ip"
fi
top_processes "$data_dir/processes" "$PT_SUMMARY_SKIP"
notable_processes_info "$data_dir/notable_procs" "$PT_SUMMARY_SKIP"
if [ -n "$CMD_VMSTAT" ]; then
touch "$data_dir/vmstat"
(
$CMD_VMSTAT 1 $OPT_SLEEP > "$data_dir/vmstat"
) &
fi
}
# Try to find all sorts of different files that say what the release is.
find_release_and_kernel () {
local file="$1"
local platform="$2"
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 _which lsb_release >/dev/null 2>&1; then
release="$(lsb_release -ds) ($(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" ]; 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" >> "$file"
echo "release $release" >> "$file"
}
cpu_and_os_arch () {
local file="$1"
local platform="$2"
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" ]; then
if $CMD_SYSCTL hw.machine_arch | grep -v 'i[36]86' >/dev/null; then
CPU_ARCH='64-bit'
fi
elif [ "${platform}" = "SunOS" ]; then
if isainfo -b | grep 64 >/dev/null ; then
CPU_ARCH="64-bit"
fi
fi
if [ -z "$CMD_FILE" ]; then
OS_ARCH='N/A'
elif $CMD_FILE /bin/sh | grep '64-bit' >/dev/null; then
OS_ARCH='64-bit'
fi
echo "CPU_ARCH $CPU_ARCH" >> "$file"
echo "OS_ARCH $OS_ARCH" >> "$file"
}
# We look in dmesg for virtualization information first, because it's often
# available to non-root users and usually has telltale signs. It's most
# reliable to look at /var/log/dmesg if possible. There are a number of
# other ways to find out if a system is virtualized.
find_virtualization () {
local vars_file="$1"
local platform="$2"
local dmesg_file="$3"
local lspci_file="$4"
local tempfile="$TMPDIR/find_virtualziation.tmp"
local virt=""
if [ -s "$dmesg_file" ]; then
virt="$(parse_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 [ -n "$CMD_PRTDIAG" ] && $CMD_PRTDIAG > "$tempfile" 2>/dev/null; then
virt="$(parse_virtualization_generic "$tempfile" )"
elif [ -n "$CMD_SMBIOS" ] && $CMD_SMBIOS > "$tempfile" 2>/dev/null; then
virt="$(parse_virtualization_generic "$tempfile" )"
fi
elif [ -e /proc/user_beancounters ]; then
virt="OpenVZ/Virtuozzo"
fi
echo "virt ${virt:-No virtualization detected}" >> "$vars_file"
}
# TODO: Maybe worth it to just dump dmidecode once and parse that?
dmidecode_system_info () {
local file="$1"
if [ -n "${CMD_DMIDECODE}" ]; then
local vendor="$($CMD_DMIDECODE -s system-manufacturer 2>/dev/null | sed 's/ *$//g')"
echo "vendor ${vendor}" >> "$file"
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}" >> "$file"
echo "servicetag ${servicetag:-Not found}" >> "$file"
fi
fi
}
find_memory_stats () {
local file="$1"
local platform="$2"
if [ "${platform}" = "Linux" ]; then
free -b > "$file"
cat /proc/meminfo >> "$file"
elif [ "${platform}" = "SunOS" ]; then
$CMD_PRTCONF | awk -F: '/Memory/{print $2}' > "$file"
fi
}
mounted_fs_info () {
local file="$1"
local platform="$2"
local skip="${3:-$PT_SUMMARY_SKIP}"
if echo "${skip}" | grep -v MOUNT >/dev/null; then
if [ "${platform}" != "SunOS" ]; then
local cmd="df -h"
if [ "${platform}" = "Linux" ]; then
cmd="df -h -P"
fi
$cmd | sort > "$TMPDIR/mounted_fs_info.tmp"
mount | sort | join "$TMPDIR/mounted_fs_info.tmp" - > "$file"
fi
fi
}
# ########################################################################
# We look in lspci first because it's more reliable, then dmesg, because it's
# often available to non-root users. It's most reliable to look at
# /var/log/dmesg if possible.
# ########################################################################
raid_controller () {
local file="$1"
local dmesg_file="$2"
local lspci_file="$3"
local tempfile="$TMPDIR/raid_controller.tmp"
local controller=""
if [ -s "$lspci_file" ]; then
controller="$(parse_raid_controller_lspci "$lspci_file")"
fi
if [ -z "${controller}" ] && [ -s "$dmesg_file" ]; then
controller="$(parse_raid_controller_dmesg "$dmesg_file")"
fi
echo "raid_controller ${controller:-No RAID controller detected}" >> "$file"
}
schedulers_and_queue_size () {
local file="$1"
local disk_partitioning_file="$2"
local disks="$(ls /sys/block/ | grep -v -e ram -e loop -e 'fd[0-9]')"
echo "disks $disks" >> "$file"
echo "" > "$disk_partitioning_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}" >> "$disk_partitioning_file" 2>/dev/null
fi
done
}
top_processes () {
local top_processes_file="$1"
local skip="${2:-"$PT_SUMMARY_SKIP"}"
if echo "${skip}" | grep -v PROCESS >/dev/null; then
if [ -n "$CMD_PRSTAT" ]; then
$CMD_PRSTAT | head > "$top_processes_file"
elif [ -n "$CMD_TOP" ]; then
local cmd="$CMD_TOP -bn 1"
if [ "${platform}" = "FreeBSD" ]; then
cmd="$CMD_TOP -b -d 1"
fi
$cmd | sed -e 's# *$##g' -e '/./{H;$!d;}' -e 'x;/PID/!d;' | grep . | head > "$top_processes_file"
fi
fi
}
notable_processes_info () {
local notable_processes_file="$1"
local skip="${2:-"$PT_SUMMARY_SKIP"}"
if echo "${skip}" | grep -v PROCESS >/dev/null; then
local sshd_pid=$(_pidof sshd)
echo " PID OOM COMMAND" > "$notable_processes_file"
# First, let's find the oom value of sshd
if [ "$sshd_pid" ]; then
echo "$sshd_pid $(get_oom_of_pid $sshd_pid) sshd" >> "$notable_processes_file"
else
_d "sshd doesn't appear to be running"
fi
# Now, let's find if any process has an oom value of -17
ps -eo pid,ucomm | tail -n +2 | while read pid proc; do
[ "$proc" = "sshd" ] && continue
local oom=$(get_oom_of_pid $pid)
if [ "$oom" ] && [ "$oom" != "?" ] && [ "$oom" -eq -17 ]; then
printf "%5s %+2d %s\n" $pid $oom $proc >> "$notable_processes_file"
fi
done
fi
}
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
psrinfo -v > "$data_dir/psrinfo_minus_v"
fi
}
# ########################################################################
# Attempt to get, parse, and print RAID controller status from possibly
# proprietary management software. Any executables that are normally stored
# in a weird location, such as /usr/StorMan/arcconf, should have their
# location added to $PATH at the beginning of main().
# ########################################################################
propietary_raid_controller () {
local file="$1"
local variable_file="$2"
local data_dir="$3"
local controller="$4"
rm -f "$file"
touch "$file"
notfound=""
if [ "${controller}" = "AACRAID" ]; then
if ! _which arcconf >/dev/null 2>&1; then
notfound="e.g. http://www.adaptec.com/en-US/support/raid/scsi_raid/ASR-2120S/"
elif arcconf getconfig 1 > "$file" 2>/dev/null; then
echo "internal::raid_opt 1" >> "$variable_file"
fi
elif [ "${controller}" = "HP Smart Array" ]; then
if ! _which hpacucli >/dev/null 2>&1; then
notfound="your package repository or the manufacturer's website"
elif 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 ! _which MegaCli64 >/dev/null 2>&1; then
notfound="your package repository or the manufacturer's website"
else
echo "internal::raid_opt 3" >> "$variable_file"
MegaCli64 -AdpAllInfo -aALL -NoLog > "$data_dir/lsi_megaraid_adapter_info.tmp" 2>/dev/null
MegaCli64 -AdpBbuCmd -GetBbuStatus -aALL -NoLog > "$data_dir/lsi_megaraid_bbu_status.tmp" 2>/dev/null
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
# ###########################################################################

View File

@@ -24,6 +24,7 @@
set -u
# Global variables.
PTDEBUG="${PTDEBUG:-""}"
EXIT_STATUS=0
log() {
@@ -41,6 +42,10 @@ die() {
exit 1
}
_d () {
[ "$PTDEBUG" ] && echo "# $(log "$@")" >&2
}
# ###########################################################################
# End log_warn_die package
# ###########################################################################

View File

@@ -0,0 +1,113 @@
# This program is copyright 2011 Percona Inc.
# Feedback and improvements are welcome.
#
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTIBILITY 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.
# ###########################################################################
# report_formatting package
# ###########################################################################
# Package: report_formatting
# Common report formatting functions for the summary tools.
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;
}'
# Does fuzzy rounding: rounds to nearest interval, but the interval gets larger
# as the number gets larger. This is to make things easier to diff.
fuzz () {
_d "fuzz: $1"
echo $1 | awk "{fuzzy_var=\$1; ${fuzzy_formula} print fuzzy_var;}"
}
# Fuzzy computes the percent that $1 is of $2
fuzzy_pct () {
local pct="$(echo $1 $2 | awk '{ if ($2 > 0) { printf "%d", $1/$2*100; } else {print 0} }')";
echo "$(fuzz "${pct}")%"
}
# Prints a section header. All spaces in the string passed in are replaced
# with #'s and all underscores with spaces.
section () {
local str="$1"
local line="$(printf '#_%-60s' "${str}_" | sed -e 's/[[:space:]]/#/g' -e 's/_/ /g')"
printf "%s\n" "${line}"
}
NAME_VAL_LEN=12
name_val () {
# We use $NAME_VAL_LEN here because the two summary tools, as well as
# the tests, use diffent widths.
printf "%+*s | %s\n" "${NAME_VAL_LEN}" "$1" "$2"
}
# Sub: shorten
# Shorten a value in bytes to another representation.
#
shorten() {
local num="$1"
local prec="${2:-2}"
local div="${3:-1024}"
echo "$num" | awk -v prec="$prec" -v div="$div" '
{
size = 4;
val = $1;
unit = val >= 1099511627776 ? "T" : val >= 1073741824 ? "G" : val >= 1048576 ? "M" : val >= 1024 ? "k" : "";
while ( int(val) && !(val % 1024) ) {
val /= 1024;
}
while ( val > 1000 ) {
val /= div;
}
printf "%.*f%s", prec, val, 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
# ###########################################################################

157
lib/bash/summary_common.sh Normal file
View File

@@ -0,0 +1,157 @@
# This program is copyright 2011-2012 Percona Inc.
# Feedback and improvements are welcome.
#
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTIBILITY 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.
# ###########################################################################
# summary_common package
# ###########################################################################
# Package: summary_common
# Common functions between the summary packages.
set -u
# Tries to find the niceness of the passed in PID. First with ps, and
# failing that, with a bit of C, using getpriority().
# Returns the nice for the pid, or "?" if it can't find any.
get_nice_of_pid () {
local pid="$1"
local niceness=$(ps -p $pid -o nice | tail -n+2 | awk '{print $1; exit;}')
if [ -n "${niceness}" ]; then
echo $niceness
else
local tmpfile="$TMPDIR/nice_through_c.tmp.c"
_d "Getting the niceness from ps failed, somehow. We are about to try this:"
cat <<EOC > "$tmpfile"
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>
#include <stdio.h>
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
}
# Fetches the oom value for a given pid.
# To avoi deprecation warnings, tries /proc/PID/oom_score_adj first.
# Will only work if /proc/cpuinfo is available.
get_oom_of_pid () {
local pid="$1"
local oom_adj=""
if [ -n "${pid}" ] && [ -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
}
CMD_FILE="$( _which file 2>/dev/null )"
CMD_NM="$( _which nm 2>/dev/null )"
CMD_OBJDUMP="$( _which objdump 2>/dev/null )"
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"
return 0
else
echo "No"
return 1
fi
}
setup_data_dir () {
local data_dir=""
if [ -z "$OPT_SAVE_DATA" ]; then
# User didn't specify a --save-data dir, so use a sub-dir in our tmpdir.
mkdir "$TMPDIR/data" || die "Cannot mkdir $TMPDIR/data"
data_dir="$TMPDIR/data"
else
# Check the user's --save-data dir.
if [ ! -d "$OPT_SAVE_DATA" ]; then
mkdir "$OPT_SAVE_DATA" || die "Cannot mkdir $OPT_SAVE_DATA"
fi
touch "$OPT_SAVE_DATA/test" || die "Cannot write to $OPT_SAVE_DATA"
rm "$OPT_SAVE_DATA/test" || die "Cannot rm $OPT_SAVE_DATA/test"
data_dir="$OPT_SAVE_DATA"
fi
echo "$data_dir"
}
# gets a value from the passed in file. Returns _GET_VAR_DEFAULT if it doesn't
# exist, which unless changed is 0.
_GET_VAR_DEFAULT=0
get_var () {
local varname="$1"
local file="$2"
local v="$(awk "\$1 ~ /^${varname}$/ { print \$2 }" "${file}")"
echo "${v:-$_GET_VAR_DEFAULT}"
}
# ###########################################################################
# End summary_common package
# ###########################################################################