integ/tools/engtools/hostdata-collectors/scripts/engtools_util.sh
Martin Chen dba551a518 Fix linters error and enable linters zuul gate
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>
2018-09-07 01:50:28 +08:00

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
}