dba551a518
Fix below linters errors E010 The "do" should be on same line as for E010 The "do" should be on same line as while E011 Then keyword is not on same line as if or elif keyword E020 Function declaration not in format ^function name {$ Ignore: E041 Arithmetic expansion using $[ is deprecated for $(( E042 local declaration hides errors E043 Arithmetic compound has inconsistent return semantics E044 Use [[ for non-POSIX comparisions Story: 2003366 Task: 24423 Change-Id: I8b6b72e702d3e89d1813772d6bf16819e28e818c Signed-off-by: Martin Chen <haochuan.z.chen@intel.com>
480 lines
12 KiB
Bash
480 lines
12 KiB
Bash
#!/bin/bash
|
|
TOOLNAME=$(basename $0)
|
|
PIDFILE=/var/run/${TOOLNAME}.pid
|
|
TOOL_DEBUG=1
|
|
TOOL_EXIT_SIGNAL=0
|
|
TOOL_USR1_SIGNAL=0
|
|
TOOL_USR2_SIGNAL=0
|
|
TOOL_TTY=0
|
|
if tty 1>/dev/null ; then
|
|
TOOL_TTY=1
|
|
fi
|
|
|
|
# [ JGAULD : SHOULD RENAME TO TOOL_X ]
|
|
OPT_USE_INTERVALS=0
|
|
OPT_FOREVER=0
|
|
PERIOD_MIN=5
|
|
INTERVAL_SEC=60
|
|
CPULIST=0
|
|
|
|
# Include lsb functions
|
|
if [ -d /lib/lsb ]; then
|
|
. /lib/lsb/init-functions
|
|
else
|
|
. /etc/init.d/functions
|
|
fi
|
|
# Lightweight replacement for pidofproc -p <pid>
|
|
function check_pidfile {
|
|
local pidfile pid
|
|
|
|
OPTIND=1
|
|
while getopts p: opt ; do
|
|
case "$opt" in
|
|
p)
|
|
pidfile="$OPTARG"
|
|
;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND - 1))
|
|
|
|
read pid < "${pidfile}"
|
|
if [ -n "${pid:-}" ]; then
|
|
if $(kill -0 "${pid:-}" 2> /dev/null); then
|
|
echo "$pid"
|
|
return 0
|
|
elif ps "${pid:-}" >/dev/null 2>&1; then
|
|
echo "$pid"
|
|
return 0 # program is running, but not owned by this user
|
|
else
|
|
return 1 # program is dead and /var/run pid file exists
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# tools_init - initialize tool resources
|
|
function tools_init {
|
|
local rc=0
|
|
local error=0
|
|
TOOLNAME=$(basename $0)
|
|
|
|
# Check for sufficient priviledges
|
|
if [ $UID -ne 0 ]; then
|
|
ERRLOG "${NAME} requires sudo/root access."
|
|
return 1
|
|
fi
|
|
|
|
# Check for essential binaries
|
|
ECHO=$(which echo 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ECHO=echo # use bash built-in echo
|
|
${ECHO} "FATAL, 'echo' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
DATE=$(which date 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
${ECHO} "FATAL, 'date' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
# Check for standard linux binaries, at least can use LOG functions now
|
|
# - these are used in tools_header
|
|
CAT=$(which cat 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ERRLOG "'cat' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
ARCH=$(which arch 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ERRLOG "'arch' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
SED=$(which sed 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ERRLOG "'sed' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
GREP=$(which grep 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ERRLOG "'grep' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
WC=$(which wc 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ERRLOG "'wc' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
UNAME=$(which uname 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ERRLOG "'uname' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
SORT=$(which sort 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ERRLOG "'sort' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
TR=$(which tr 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ERRLOG "'tr' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
AWK=$(which awk 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ERRLOG "'awk' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
PKILL=$(which pkill 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ERRLOG "'pkill' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
LS=$(which ls 2>/dev/null)
|
|
rc=$?
|
|
if [ $rc -ne 0 ]; then
|
|
ERRLOG "'ls' not found, rc=$rc";
|
|
error=$rc
|
|
fi
|
|
|
|
# The following block is needed for LSB systems such as Windriver Linux.
|
|
# The utility is not available on CentOS so comment it out.
|
|
# Generic utility, but may not be available
|
|
# LSB=$(which lsb_release 2>/dev/null)
|
|
# rc=$?
|
|
# if [ $rc -ne 0 ]; then
|
|
# WARNLOG "'lsb_release' not found, rc=$rc";
|
|
# fi
|
|
|
|
# Let parent program decide what to do with the errors,
|
|
# give ominous warning
|
|
if [ $error -eq 1 ]; then
|
|
WARNLOG "possibly cannot continue, missing linux binaries"
|
|
fi
|
|
|
|
# Check if tool was previously running
|
|
if [ -e ${PIDFILE} ]; then
|
|
# [ JGAULD - remove pidofproc() / LSB compatibility issue ]
|
|
if check_pidfile -p "${PIDFILE}" >/dev/null; then
|
|
ERRLOG "${PIDFILE} exists and ${TOOLNAME} is running"
|
|
return 1
|
|
else
|
|
# remove pid file
|
|
WARNLOG "${PIDFILE} exists but ${TOOLNAME} is not running; cleaning up"
|
|
rm -f ${PIDFILE}
|
|
fi
|
|
fi
|
|
|
|
# Create pid file
|
|
echo $$ > ${PIDFILE}
|
|
|
|
# Setup trap handler - these signals trigger child shutdown and cleanup
|
|
trap tools_exit_handler INT HUP TERM EXIT
|
|
trap tools_usr1_handler USR1
|
|
trap tools_usr2_handler USR2
|
|
|
|
return ${rc}
|
|
}
|
|
|
|
# tools_cleanup() - terminate child processes
|
|
function tools_cleanup {
|
|
# restore signal handling to default behaviour
|
|
trap - INT HUP TERM EXIT
|
|
trap - USR1 USR2
|
|
|
|
local VERBOSE_OPT=''
|
|
if [ "$1" -ne "0" ]; then
|
|
LOG "cleanup invoked with code: $1"
|
|
if [ ${TOOL_DEBUG} -ne 0 ]; then
|
|
VERBOSE_OPT='-v'
|
|
fi
|
|
fi
|
|
|
|
|
|
# stop all processes launched from this process
|
|
pkill -TERM -P $$
|
|
if [ "$1" -ne "0" ]; then
|
|
sleep 1
|
|
fi
|
|
|
|
# OK, if the above didn't work, use force
|
|
pkill -KILL -P $$
|
|
|
|
# remove pid file
|
|
if [ -e ${PIDFILE} ]; then
|
|
rm -f ${VERBOSE_OPT} ${PIDFILE}
|
|
fi
|
|
exit $1
|
|
}
|
|
|
|
# tools_exit_handler() - exit handler routine
|
|
function tools_exit_handler {
|
|
TOOL_EXIT_SIGNAL=1
|
|
tools_cleanup 128
|
|
}
|
|
# tools_usr1_handler() - USR1 handler routine
|
|
function tools_usr1_handler {
|
|
TOOL_USR1_SIGNAL=1
|
|
LOG "caught USR1"
|
|
}
|
|
# tools_usr2_handler() - USR2 handler routine
|
|
function tools_usr2_handler {
|
|
TOOL_USR2_SIGNAL=1
|
|
LOG "caught USR1"
|
|
}
|
|
|
|
# LOG(), WARNLOG(), ERRLOG() - simple print log functions (not logger)
|
|
function LOG {
|
|
local tstamp_H=$( date +"%Y-%0m-%0e %H:%M:%S" )
|
|
echo "${tstamp_H} ${HOSTNAME} $0($$): $@";
|
|
}
|
|
|
|
function LOG_NOCR {
|
|
local tstamp_H=$( date +"%Y-%0m-%0e %H:%M:%S" )
|
|
echo -n "${tstamp_H} ${HOSTNAME} $0($$): $@";
|
|
}
|
|
|
|
function WARNLOG {
|
|
LOG "WARN $@";
|
|
}
|
|
|
|
function ERRLOG {
|
|
LOG "ERROR $@";
|
|
}
|
|
|
|
# TOOL_HIRES_TIME() - easily parsed date/timestamp and hi-resolution uptime
|
|
function TOOL_HIRES_TIME {
|
|
echo "time: " $( ${DATE} +"%a %F %H:%M:%S.%N %Z %z" ) "uptime: " $( cat /proc/uptime )
|
|
}
|
|
|
|
# set_affinity() - set affinity for current script if a a CPULIST is defined
|
|
function set_affinity {
|
|
local CPULIST=$1
|
|
if [ -z "${CPULIST}" ]; then
|
|
return
|
|
fi
|
|
|
|
# Set cpu affinity for current program
|
|
local TASKSET=$(which taskset 2>/dev/null)
|
|
if [ -x "${TASKSET}" ]; then
|
|
${TASKSET} -pc ${CPULIST} $$ 2>/dev/null
|
|
fi
|
|
}
|
|
|
|
# cmd_idle_priority() - command to set nice + ionice
|
|
function cmd_idle_priority {
|
|
local NICE=""
|
|
local IONICE=""
|
|
|
|
NICE=$( which nice 2>/dev/null )
|
|
if [ $? -eq 0 ]; then
|
|
NICE="${NICE} -n 19"
|
|
else
|
|
NICE=""
|
|
fi
|
|
IONICE=$( which ionice 2>/dev/null )
|
|
if [ $? -eq 0 ]; then
|
|
IONICE="${IONICE} -c 3"
|
|
else
|
|
IONICE=""
|
|
fi
|
|
echo "${NICE} ${IONICE}"
|
|
}
|
|
|
|
|
|
# print_separator() - print a horizontal separation line '\u002d' is '-'
|
|
function print_separator {
|
|
printf '\u002d%.s' {1..80}
|
|
printf '\n'
|
|
}
|
|
|
|
# tools_header() - print out common GenWare tools header
|
|
function tools_header {
|
|
local TOOLNAME=$(basename $0)
|
|
|
|
# Get timestamp
|
|
#local tstamp=$( date +"%Y-%0m-%0e %H:%M:%S" 2>/dev/null )
|
|
local tstamp=$( date --rfc-3339=ns | cut -c1-23 2>/dev/null )
|
|
|
|
# Linux Generic
|
|
local UPTIME=/proc/uptime
|
|
|
|
# Get number of online cpus
|
|
local CPUINFO=/proc/cpuinfo
|
|
local online_cpus=$( cat ${CPUINFO} | grep -i ^processor | wc -l 2>/dev/null )
|
|
|
|
# Get load average, run-queue size, and number of threads
|
|
local LOADAVG=/proc/loadavg
|
|
local LDAVG=( `cat ${LOADAVG} | sed -e 's#[/]# #g' 2>/dev/null` )
|
|
|
|
# Get current architecture
|
|
local arch=$( uname -m )
|
|
|
|
# Determine processor name (there are many different formats... *sigh* )
|
|
# - build up info from multiple lines
|
|
local processor='unk'
|
|
local NAME=$( cat ${CPUINFO} | grep \
|
|
-e '^cpu\W\W:' \
|
|
-e ^'cpu model' \
|
|
-e ^'model name' \
|
|
-e ^'system type' \
|
|
-e ^Processor \
|
|
-e ^[Mm]achine | \
|
|
sort -u | awk 'BEGIN{FS=":";} {print $2;}' | \
|
|
tr '\n' ' ' | tr -s [:blank:] 2>/dev/null )
|
|
if [ ! -z "${NAME}" ]; then
|
|
processor=${NAME}
|
|
fi
|
|
|
|
# Determine processor speed (abort grep after first match)
|
|
local speed='unk'
|
|
local BOGO=$( cat ${CPUINFO} | grep -m1 -e ^BogoMIPS -e ^bogomips | \
|
|
awk 'BEGIN{FS=":";} {printf "%.1f", $2;}' 2>/dev/null )
|
|
local MHZ=$( cat ${CPUINFO} | grep -m1 -e ^'cpu MHz' -e ^clock | \
|
|
awk 'BEGIN{FS=":";} {printf "%.1f", $2;}' 2>/dev/null )
|
|
local MHZ2=$( cat ${CPUINFO} | grep -m1 -e ^Cpu0ClkTck -e ^'cycle frequency' | \
|
|
awk 'BEGIN{FS=":";} {printf "%.1f", $2/1.0E6;}' 2>/dev/null )
|
|
if [ ! -z "${MHZ}" ]; then
|
|
speed=${MHZ}
|
|
elif [ ! -z "${MHZ2}" ]; then
|
|
speed=${MHZ2}
|
|
elif [ ! -z ${BOGO} ]; then
|
|
speed=${BOGO}
|
|
fi
|
|
|
|
# Determine OS and kernel version
|
|
local os_name=$( uname -s 2>/dev/null )
|
|
local os_release=$( uname -r 2>/dev/null )
|
|
|
|
declare -a arr
|
|
|
|
local dist_id=""
|
|
# Determine OS distribution ID
|
|
if [ lsb_pres == "yes" ]; then
|
|
arr=( $( lsb_release -i 2>/dev/null ) )
|
|
dist_id=${arr[2]}
|
|
else
|
|
local dist_id=$(cat /etc/centos-release | awk '{print $1}' 2>/dev/null)
|
|
fi
|
|
|
|
local dist_rel=""
|
|
if [ lsb_pres == "yes" ]; then
|
|
# Determine OS distribution release
|
|
arr=( $( cat /proc/version | awk '{print $3}' 2>/dev/null ) )
|
|
local dist_rel=${arr[1]}
|
|
else
|
|
local dist_rel=$(cat /etc/centos-release | awk '{print $4}' 2>/dev/null)
|
|
fi
|
|
# Print generic header
|
|
echo "${TOOLNAME} -- ${tstamp} load average:${LDAVG[0]}, ${LDAVG[1]}, ${LDAVG[2]} runq:${LDAVG[3]} nproc:${LDAVG[4]}"
|
|
echo " host:${HOSTNAME} Distribution:${dist_id} ${dist_rel} ${os_name} ${os_release}"
|
|
echo " arch:${arch} processor:${processor} speed:${speed} MHz CPUs:${online_cpus}"
|
|
}
|
|
|
|
|
|
|
|
|
|
# tools_usage() - show generic tools tool usage
|
|
function tools_usage {
|
|
if [ ${OPT_USE_INTERVALS} -eq 1 ]; then
|
|
echo "usage: ${TOOLNAME} [-f] [-p <period_mins>] [-i <interval_seconds>] [-c <cpulist>] [-h]"
|
|
else
|
|
echo "Usage: ${TOOLNAME} [-f] [-p <period_mins>] [-c <cpulist>] [-h]"
|
|
fi
|
|
}
|
|
|
|
# tools_print_help() - print generic tool help
|
|
function tools_print_help {
|
|
tools_usage
|
|
echo
|
|
echo "Options:";
|
|
echo " -f : collect forever : default: none"
|
|
echo " -p <period_minutes> : overall collection period (minutes) : default: ${DEFAULT_PERIOD_MIN}"
|
|
if [ ${OPT_USE_INTERVALS} -eq 1 ]; then
|
|
echo " -i <interval_seconds> : sample interval (seconds) : default: ${DEFAULT_INTERVAL_SEC}"
|
|
fi
|
|
echo " -c <cpulist> : cpu list where tool runs (e.g., 0-1,8) : default: none"
|
|
echo
|
|
if [ ${OPT_USE_INTERVALS} -eq 1 ]; then
|
|
echo "Example: collect 5 minute period, sample every 30 seconds interval"
|
|
echo " ${TOOLNAME} -p 5 -i 30"
|
|
else
|
|
echo "Example: collect 5 minute period"
|
|
echo " ${TOOLNAME} -p 5"
|
|
fi
|
|
}
|
|
|
|
# tools_parse_options() -- parse common options for tools scripts
|
|
function tools_parse_options {
|
|
# check for no arguments, print usage
|
|
if [ $# -eq "0" ]; then
|
|
tools_usage
|
|
tools_cleanup 0
|
|
exit 0
|
|
fi
|
|
|
|
# parse the input arguments
|
|
while getopts "fp:i:c:h" Option; do
|
|
case $Option in
|
|
f)
|
|
OPT_FOREVER=1
|
|
PERIOD_MIN=60
|
|
;;
|
|
p) PERIOD_MIN=$OPTARG ;;
|
|
i)
|
|
OPT_USE_INTERVALS=1
|
|
INTERVAL_SEC=$OPTARG
|
|
;;
|
|
c) CPULIST=$OPTARG ;;
|
|
h)
|
|
tools_print_help
|
|
tools_cleanup 0
|
|
exit 0
|
|
;;
|
|
*)
|
|
tools_usage
|
|
tools_cleanup 0
|
|
exit 0
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# validate input arguments
|
|
PERIOD_MAX=$[4*24*60]
|
|
INTERVAL_MAX=$[60*60]
|
|
|
|
error=0
|
|
if [[ ${PERIOD_MIN} -lt 1 || ${PERIOD_MIN} -gt ${PERIOD_MAX} ]]; then
|
|
echo "-p <period_mid> must be > 0 and <= ${PERIOD_MAX}."
|
|
error=1
|
|
fi
|
|
if [[ ${INTERVAL_SEC} -lt 1 || ${INTERVAL_SEC} -gt ${INTERVAL_MAX} ]]; then
|
|
echo "-i <interval> must be > 0 and <= ${INTERVAL_MAX}."
|
|
error=1
|
|
fi
|
|
if [ ${error} -eq 1 ]; then
|
|
tools_cleanup 0
|
|
exit 1
|
|
fi
|
|
}
|