#!/bin/sh # Copyright (C) 2025 Michael Erdely All Rights Reserved. # SPDX-FileCopyrightText: 2024 Splunk, Inc. # SPDX-License-Identifier: Apache-2.0 # shellcheck disable=SC1091 . "$(dirname "$0")"/common.sh assertHaveCommand column HEADER='Datetime pctUser pctNice pctSystem pctIowait pctIdle OSName OS_version IP_address CPU' HEADERIZE="BEGIN {print \"$HEADER\"}" PRINTF='{printf "%-28s %9s %9s %9s %9s %9s %-35s %15s %-16s %-3s\n", datetime, pctUser, pctNice, pctSystem, pctIowait, pctIdle, OSName, OS_version, IP_address,cpu}' FILL_DIMENSIONS='{length(IP_address) || IP_address = "?";length(OS_version) || OS_version = "?";length(OSName) || OSName = "?"}' if [ "$KERNEL" = "Linux" ] ; then queryHaveCommand sar FOUND_SAR=$? queryHaveCommand mpstat FOUND_MPSTAT=$? if [ ! -f "/etc/os-release" ] ; then DEFINE="-v OSName=$(cat /etc/*release | head -n 1| awk -F" release " '{print $1}'| tr ' ' '_') -v OS_version=$(cat /etc/*release | head -n 1| awk -F" release " '{print $2}' | cut -d\. -f1) -v IP_address=$(ip -4 route show default | awk '{print $9}')" else DEFINE="-v OSName=$(cat /etc/*release | grep '\bNAME=' | cut -d '=' -f2 | tr ' ' '_' | cut -d\" -f2) -v OS_version=$(cat /etc/*release | grep -E '\b(VERSION|BUILD)_ID=' | cut -d '=' -f2 | cut -d\" -f2) -v IP_address=$(ip -4 route show default | awk '{print $9}')" fi if [ $FOUND_SAR -eq 0 ] ; then CMD='sar -P ALL 2 5' # shellcheck disable=SC2016 FORMAT='{datetime = strftime("%m/%d/%y_%H:%M:%S_%Z"); cpu=$(NF-6); pctUser=$(NF-5); pctNice=$(NF-4); pctSystem=$(NF-3); pctIowait=$(NF-2); pctIdle=$NF;OSName=OSName;OS_version=OS_version;IP_address=IP_address;}' elif [ $FOUND_MPSTAT -eq 0 ] ; then CMD='mpstat -P ALL 2 5' # shellcheck disable=SC2016 FORMAT='{datetime = strftime("%m/%d/%y_%H:%M:%S_%Z"); cpu=$(NFIELDS-10); pctUser=$(NFIELDS-9); pctNice=$(NFIELDS-8); pctSystem=$(NFIELDS-7); pctIowait=$(NFIELDS-6); pctIdle=$NF;OSName=OSName;OS_version=OS_version;IP_address=IP_address;}' else failLackMultipleCommands sar mpstat fi # shellcheck disable=SC2016 FILTER='($0 ~ /CPU/) { if($(NF-1) ~ /gnice/){ NFIELDS=NF; } else {NFIELDS=NF+1;} next} /Average|Linux|^$|%/ {next}' elif [ "$KERNEL" = "SunOS" ] ; then formatted_date=$(date +"%m/%d/%y_%H:%M:%S_%Z") if [ "$SOLARIS_8" = "true" ] || [ "$SOLARIS_9" = "true" ] ; then CMD='eval mpstat -a -p 1 2 | tail -1 | sed "s/^[ ]*0/all/"; mpstat -p 1 2 | tail -r' else CMD='eval mpstat -aq -p 1 2 | tail -1 | sed "s/^[ ]*0/all/"; mpstat -q -p 1 2 | tail -r' fi DEFINE="-v OSName=$(uname -s) -v OS_version=$(uname -r) -v IP_address=$(ifconfig -a | grep 'inet ' | grep -v 127.0.0.1 | cut -d\ -f2 | head -n 1)" assertHaveCommand "$CMD" # shellcheck disable=SC2016 FILTER='($1=="CPU") {exit 1}' # shellcheck disable=SC2016 FORMAT='{datetime="'"$formatted_date"'"; cpu=$1; pctUser=$(NF-4); pctNice="0"; pctSystem=$(NF-3); pctIowait=$(NF-2); pctIdle=$(NF-1);OSName=OSName;OS_version=OS_version;IP_address=IP_address;}' elif [ "$KERNEL" = "AIX" ] ; then queryHaveCommand mpstat queryHaveCommand lparstat FOUND_MPSTAT=$? FOUND_LPARSTAT=$? DEFINE="-v OSName=$(uname -s) -v OSVersion=$(oslevel -r | cut -d'-' -f1) -v IP_address=$(ifconfig -a | grep 'inet ' | grep -v 127.0.0.1 | cut -d\ -f2 | head -n 1)" if [ $FOUND_MPSTAT -eq 0 ] && [ $FOUND_LPARSTAT -eq 0 ] ; then # Get extra fields from lparstat COUNT=$(lparstat | grep " app" | wc -l) if [ $COUNT -gt 0 ] ; then # Fetch value from "app" column of lparstat output FETCH_APP_COL_NUM='BEGIN {app_col_num = 8} { if($0 ~ /System configuration|^$/) {next} if($0 ~ / app/) { for(i=1; i<=NF; i++) { if($i == "app") { app_col_num = i; break; } } print app_col_num; exit 0; } }' APP_COL_NUM=$(lparstat | awk "$FETCH_APP_COL_NUM") CPUPool=$(lparstat | tail -1 | awk -v APP_COL_NUM=$APP_COL_NUM -F " " '{print $APP_COL_NUM}') else CPUPool=0 fi # Fetch other required fields from lparstat output OnlineVirtualCPUs=$(lparstat -i | grep "Online Virtual CPUs" | awk -F " " '{print $NF}') EntitledCapacity=$(lparstat -i | grep "Entitled Capacity " | awk -F " " '{print $NF}') DEFINE_LPARSTAT_FIELDS="-v CPUPool=$CPUPool -v OnlineVirtualCPUs=$OnlineVirtualCPUs -v EntitledCapacity=$EntitledCapacity" # Get cpu stats using mpstat command and manipulate the output for adding extra fields CMD='mpstat -a 2 5' # shellcheck disable=SC2016 FORMAT=' function get_current_time() { # Use "date" to fetch the current time and store it in a variable command = "date +\"%m/%d/%y_%H:%M:%S_%Z\""; command | getline datetime; close(command); return datetime; } $1 ~ /^-+$/ { next } BEGIN {flag = 0} { if($0 ~ /System configuration|^$/) {next} if($0 ~ /cpu / && flag == 1) {next} if(flag == 1) { for(i=NF+8; i>=8; i--) { $i = $(i-7); } # Prepend Datetime, OSName, OS_version, IP_address values $1 = get_current_time(); $2 = OSName; $3 = OSVersion/1000; $4 = IP_address; # Prepend lparstat field values if($0 ~ /ALL/) { $5 = CPUPool; $6 = OnlineVirtualCPUs; $7 = EntitledCapacity; } else { $5 = "-"; $6 = "-"; $7 = "-"; } } if($0 ~ /cpu /) { for(i=NF+8; i>=8; i--) { $i = $(i-7); } # Prepend Datetime, OSName, OS_version, IP_address headers $1 = "Datetime"; $2 = "OSName"; $3 = "OS_version"; $4 = "IP_address"; # Prepend lparstat field headers $5 = "CPUPool"; $6 = "OnlineVirtualCPUs"; $7 = "EntitledCapacity"; flag = 1; } printf $1; for(i=2; i<=NF; i++) { printf "%17s ", $i; } print ""; }' fi $CMD | tee "$TEE_DEST" | $AWK $DEFINE $DEFINE_LPARSTAT_FIELDS "$FORMAT $FILL_DIMENSIONS" | column -t echo "Cmd = [$CMD]; | $AWK $DEFINE $DEFINE_LPARSTAT_FIELDS '$FORMAT $FILL_DIMENSIONS'" >>"$TEE_DEST" exit elif [ "$KERNEL" = "Darwin" ] ; then HEADER='Datetime pctUser pctSystem pctIdle OSName OS_version IP_address CPU' HEADERIZE="BEGIN {print \"$HEADER\"}" PRINTF='{printf "%-28s %9s %9s %9s %-35s %15s %-16s %-3s\n", datetime, pctUser, pctSystem, pctIdle, OSName, OS_version, IP_address, cpu}' # top command here is used to get a single instance of cpu metrics CMD='top -l 5 -s 2' assertHaveCommand "$CMD" # FILTER here skips all the rows that doesn't match "CPU". # shellcheck disable=SC2016 FILTER='($1 !~ "CPU") {next;}' DEFINE="-v OSName=$(uname -s) -v OS_version=$(uname -r) -v IP_address=$(ifconfig -a | grep 'inet ' | grep -v 127.0.0.1 | cut -d\ -f2 | head -n 1)" # FORMAT here removes '%'in the end of the metrics. # shellcheck disable=SC2016 FORMAT=' function get_current_time() { # Use "date" to fetch the current time and store it in a variable command = "date +\"%m/%d/%y_%H:%M:%S_%Z\""; command | getline datetime; close(command); return datetime; } function remove_char(string, char_to_remove) { sub(char_to_remove, "", string); return string; } { datetime=get_current_time(); cpu="all"; pctUser = remove_char($3, "%"); pctSystem = remove_char($5, "%"); pctIdle = remove_char($7, "%"); OSName=OSName; OS_version=OS_version; IP_address=IP_address; }' elif [ "$KERNEL" = "OpenBSD" ] ; then formatted_date=$(date +"%m/%d/%y_%H:%M:%S_%Z") CMD='eval top -1 -b; top -b' assertHaveCommand "$CMD" # shellcheck disable=SC2016 FILTER='($0 !~ "^([0-9]+[\t ]+)?CPU"){next;}' # shellcheck disable=SC2016 DEFINE="-v OSName=$(uname -s) -v OS_version=$(uname -r) -v IP_address=$(ifconfig -a | grep 'inet ' | grep -v 127.0.0.1 | cut -d\ -f2 | head -n 1)" # shellcheck disable=SC2016 FORMAT='{ if ($1 ~ /^[0-9]+$/) cpu="all"; else if ($1 ~ /^CPU[0-9]+$/) cpu=substr($1,4); else cpu=0; datetime="'"$formatted_date"'"; pctUser=substr($3,1,length($3)-1); pctNice=substr($5,1,length($5)-1); pctSystem=substr($7,1,length($7)-1); pctIowait=substr($11,1,length($11)-1); pctIdle=substr($13,1,length($13)-1); }' elif [ "$KERNEL" = "FreeBSD" ] ; then formatted_date=$(date +"%m/%d/%y_%H:%M:%S_%Z") CMD='eval top -P -d2 c; top -d2 c' assertHaveCommand "$CMD" # shellcheck disable=SC2016 FILTER='($1 !~ "CPU") { next; }' # shellcheck disable=SC2016 DEFINE="-v OSName=$(uname -s) -v OS_version=$(uname -r) -v IP_address=$(ifconfig -a | grep 'inet ' | grep -v 127.0.0.1 | cut -d\ -f2 | head -n 1)" # shellcheck disable=SC2016 FORMAT='function remove_char(string, char_to_remove) { sub(char_to_remove, "", string); return string; } { datetime="'"$formatted_date"'"; } { if ($1 == "CPU:") { cpu = "all"; } else { cpu = remove_char($2, ":"); } } { pctUser = remove_char($(NF-9), "%"); pctNice = remove_char($(NF-7), "%"); pctSystem = remove_char($(NF-5), "%"); pctIdle = remove_char($(NF-1), "%"); pctIowait = "0.0"; OSName=OSName; OS_version=OS_version; IP_address=IP_address; }' fi # shellcheck disable=SC2086 $CMD | tee "$TEE_DEST" | $AWK $DEFINE "$HEADERIZE $FILTER $FORMAT $FILL_DIMENSIONS $PRINTF" header="$HEADER" | column -t echo "Cmd = [$CMD]; | $AWK $DEFINE '$HEADERIZE $FILTER $FORMAT $FILL_DIMENSIONS $PRINTF' header=\"$HEADER\"" >>"$TEE_DEST"