Import Splunk Add-On for Unix and Linux version 9.2.0

This commit is contained in:
Michael Erdely 2024-12-24 23:51:57 -05:00
commit 92ac2630a1
Signed by: mike
SSH key fingerprint: SHA256:ukbnfrRMaRYlBZXENtBTyO2jLnql5AA5m+SzZCfYQe0
77 changed files with 11487 additions and 0 deletions

92
bin/bandwidth.sh Executable file
View file

@ -0,0 +1,92 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# jscpd:ignore-start
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER='Name rxPackets_PS txPackets_PS rxKB_PS txKB_PS'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='{printf "%s %s %s %s %s\n", Name, rxPackets_PS, txPackets_PS, rxKB_PS, txKB_PS}'
# Note: For FreeBSD, bsdsar package needs to be installed. Output matches linux equivalent
if [ "$KERNEL" = "Linux" ] ; then
CMD='sar -n DEV 1 2'
# shellcheck disable=SC2016
FILTER='($0 !~ "Average" || $0 ~ "sar" || $2 ~ "lo|IFACE") {next}'
# shellcheck disable=SC2016
FORMAT='{Name=$2; rxPackets_PS=$3; txPackets_PS=$4; rxKB_PS=$5; txKB_PS=$6}'
elif [ "$KERNEL" = "SunOS" ] ; then
if [ "$SOLARIS_10" = "true" ] ; then
CMD='netstat -i 1 2'
FILTER='(NR==2||NR==3){next}'
# shellcheck disable=SC2016
EXTRACT_NAME='NR==1 {for (i=0; i< NF/3 -1; i++) { name[i]=$(i*3 + 2); location[name[i]]=i }}'
# shellcheck disable=SC2016
EXTRACT_FIELDS=' NR==4 { for (each in name){ printf "%s %s %s %s %s\n",name[each], $(5*location[name[each]]+1), $(5*location[name[each]]+3), "<n/a>","<n/a>"; }}'
PRINTF=''
FORMAT="$EXTRACT_NAME $EXTRACT_FIELDS"
elif [ "$SOLARIS_11" = "true" ] ; then
if ! dlstat 1 1 > /dev/null 2>&1 ; then
CMD='netstat -i 1 2'
FILTER='(NR==2||NR==3){next}'
# shellcheck disable=SC2016
EXTRACT_NAME='NR==1 {for (i=0; i< NF/3 -1; i++) { name[i]=$(i*3 + 2); location[name[i]]=i }}'
# shellcheck disable=SC2016
EXTRACT_FIELDS=' NR==4 { for (each in name){ printf "%s %s %s %s %s\n",name[each], $(5*location[name[each]]+1), $(5*location[name[each]]+3), "<n/a>","<n/a>"; }}'
PRINTF=''
FORMAT="$EXTRACT_NAME $EXTRACT_FIELDS"
else
CMD='dlstat 1 2'
FILTER='(NR==1||NR==2){next}'
# shellcheck disable=SC2016
FORMAT='
function to_kbps(KBPS_param){
if(KBPS_param ~ /[Kk]$/){ sub(/[A-Za-z]/,"",KBPS_param); return(KBPS_param); }
else if(KBPS_param ~ /[Gg]$/){ sub(/[A-Za-z]/,"",KBPS_param); return(KBPS_param*1024*1024); }
else if(KBPS_param ~ /[Mm]$/){ sub(/[A-Za-z]/,"",KBPS_param); return(KBPS_param*1024); }
sub(/[a-zA-Z]/,"",KBPS_param); return(KBPS_param/1024);
}
{Name=$1; rxPackets_PS=$2; txPackets_PS=$4; rxKB_PS=to_kbps($3); txKB_PS=to_kbps($5);}'
fi
else
CMD='sar -n DEV 1 2'
# shellcheck disable=SC2016
FILTER='($0 ~ "Time|sar| lo") {next}'
# shellcheck disable=SC2016
FORMAT='{Name=$2; rxPackets_PS=$5; txPackets_PS=$6; rxKB_PS=$3; txKB_PS=$4}'
fi
elif [ "$KERNEL" = "AIX" ] ; then
# Sample output: http://www-01.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.performance/nestat_in.htm
CMD='eval netstat -i -Z; sleep 1; netstat -in'
# shellcheck disable=SC2016
FILTER='($0 ~ "Name|sar|lo") {next}'
# shellcheck disable=SC2016
FORMAT='{Name=$1; rxPackets_PS=$5; txPackets_PS=$7; rxKB_PS="?"; txKB_PS="?"}'
elif [ "$KERNEL" = "Darwin" ] ; then
CMD='sar -n DEV 1 2'
# shellcheck disable=SC2016
FILTER='($0 !~ "Average" || $0 ~ "sar" || $2~/lo[0-9]|IFACE/) {next}'
# shellcheck disable=SC2016
FORMAT='{Name=$2; rxPackets_PS=$3; txPackets_PS=$5; rxKB_PS=$4/1024; txKB_PS=$6/1024}'
elif [ "$KERNEL" = "HP-UX" ] ; then
# Sample output: http://h20565.www2.hp.com/hpsc/doc/public/display?docId=emr_na-c02263324
CMD='netstat -i 1 2'
# shellcheck disable=SC2016
FILTER='($0 ~ "Name|sar| lo") {next}'
# shellcheck disable=SC2016
FORMAT='{Name=$1; rxPackets_PS=$5; txPackets_PS=$7; rxKB_PS=?; txKB_PS=?}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
CMD='sar -n DEV 1 2'
# shellcheck disable=SC2016
FILTER='($0 !~ "Average" || $0 ~ "sar" || $2 ~ "lo|IFACE") {next}'
# shellcheck disable=SC2016
FORMAT='{Name=$2; rxPackets_PS=$3; txPackets_PS=$4; rxKB_PS=$5; txKB_PS=$6}'
fi
assertHaveCommand "$CMD"
$CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $FILTER $FORMAT $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $FILTER $FORMAT $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"
# jscpd:ignore-end

138
bin/common.sh Executable file
View file

@ -0,0 +1,138 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1000-SC9999 # Reason: This script is used in all the scripts and any change in this script would require a higher effort in testing all the scripts. Hence ignoring whole file.
# # # we don't want to point OS's utilities -- e.g. ntpdate(1) -- to libraries which Splunk bundles in SPLUNK_HOME/lib/
unset LD_PRELOAD LD_LIBRARY_PATH DYLD_LIBRARY_PATH SHLIB_PATH LIBPATH
# # # NIX-203 - set LANG env variable set to en_US to avoid parsing problems in other locales
EngLocale=`locale -a | grep -i "en_US.utf"`
if [ ! -z "$EngLocale" ]; then
LC_ALL=`echo $EngLocale | awk 'NR==1 {printf $1}'`
export LC_ALL
fi
# # # are we in debug mode?
if [ $# -ge 1 -a "x$1" = "x--debug" ] ; then
DEBUG=1
TEE_DEST=`dirname $0`/debug--`basename $0`--`date | sed 's/ /_/g;s/:/-/g'`
else
DEBUG=0
TEE_DEST=/dev/null
fi
DMESG_FILE=/var/log/dmesg
OS_FILE=/etc/os-release
# # # what OS is this?
KERNEL=`uname -s`
# # # what is the Kernel version?
KERNEL_RELEASE=`uname -r`
# # # assert we are in a supported OS
AWK=awk
case "x$KERNEL" in
"xLinux")
if [ -e $OS_FILE ]; then
UBUNTU_MAJOR_VERSION=`awk -F'[".]' '/VERSION_ID=/ {print $2} ' $OS_FILE`;
OS_ID=$(awk -F'=' ' /ID_LIKE=/ {print $2}' $OS_FILE)
else
UBUNTU_MAJOR_VERSION="";
echo "$OS_FILE does not exist. UBUNTU_MAJOR_VERSION will be empty." > $TEE_DEST
fi
# # # enable check for OS versions, if needed later
if [ -e /etc/debian_version ]; then DEBIAN=true; else DEBIAN=false; fi
# # # /sbin/ is often absent in non-root users' PATH, and we want it for ifconfig(8)
PATH=$PATH:/sbin/
;;
"xSunOS")
# # # enable check for OS versions, if needed later
if [ `uname -r` = "5.8" ]; then SOLARIS_8=true; else SOLARIS_8=false; fi
if [ `uname -r` = "5.9" ]; then SOLARIS_9=true; else SOLARIS_9=false; fi
if [ `uname -r` = "5.10" ]; then SOLARIS_10=true; else SOLARIS_10=false; fi
if [ `uname -r` = "5.11" ]; then SOLARIS_11=true; else SOLARIS_11=false; fi
# # # eschew the antedeluvial awk
AWK=nawk
;;
"xDarwin")
OSX_MINOR_VERSION=`sw_vers | sed -En '/ProductVersion/ s/^[^.]+\.([0-9]+)(\.[^.])?$/\1/p'`
OSX_MAJOR_VERSION=`sw_vers | sed -En '/ProductVersion/ s/^[^0-9]+([0-9]+)\.[0-9]+(\.[^.]+)?$/\1/p'`
# OSX_GE_SNOW_LEOPARD is for backward compatiblity.
# Recommend that new code just use $OSX_MINOR_VERSION directly.
if [ "$OSX_MAJOR_VERSION" == 10 ] && [ "$OSX_MINOR_VERSION" -ge 6 ]; then
OSX_GE_SNOW_LEOPARD=true;
else
OSX_GE_SNOW_LEOPARD=false;
fi
;;
"xFreeBSD")
;;
"xAIX")
;;
"xHP-UX")
;;
*)
echo "UNIX flavor [$KERNEL] unsupported for Splunk *NIX App, quitting" > $TEE_DEST
exit 1
;;
esac
# # # check for presence of required commands; we do not assume that which(1) exists, and roll our own
queryHaveCommand () # returns 0 if found, 1 if not
{
[ "x$1" = "xeval" ] && shift
for directory in `echo $PATH | sed 's/:/ /g'`
do
[ -x $directory/$1 ] && return 0
done
return 1
}
failLackCommand ()
{
echo "Not found command [$1] on this host, quitting" > $TEE_DEST
exit 1
}
failLackMultipleCommands ()
{
echo "Not found any of commands [$*] on this host, quitting" > $TEE_DEST
exit 1
}
assertHaveCommand ()
{
queryHaveCommand $1
if [ $? -eq 1 ] ; then
failLackCommand $1
fi
}
assertHaveCommandGivenPath ()
{
[ "x$1" = "xeval" ] && shift
[ -x $1 ] && return
echo "Not found commandGivenPath [$1] on this host, quitting" > $TEE_DEST
exit 1
}
failUnsupportedScript ()
{
echo "UNIX flavor [$KERNEL] unsupported for this script, quitting" > $TEE_DEST
exit 0
}
assertInvokerIsSuperuser ()
{
[ `id -u` -eq 0 ] && return
echo "Must be superuser to run this script, quitting" > $TEE_DEST
exit 1
}
# # # check for presence of a few basic commands ubiquitous in our scripts
assertHaveCommand $AWK
assertHaveCommand egrep

184
bin/cpu.sh Executable file
View file

@ -0,0 +1,184 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER='CPU pctUser pctNice pctSystem pctIowait pctIdle'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='{printf "%-3s %9s %9s %9s %9s %9s\n", cpu, pctUser, pctNice, pctSystem, pctIowait, pctIdle}'
if [ "$KERNEL" = "Linux" ] ; then
queryHaveCommand sar
FOUND_SAR=$?
queryHaveCommand mpstat
FOUND_MPSTAT=$?
if [ $FOUND_SAR -eq 0 ] ; then
CMD='sar -P ALL 1 1'
# shellcheck disable=SC2016
FORMAT='{cpu=$(NF-6); pctUser=$(NF-5); pctNice=$(NF-4); pctSystem=$(NF-3); pctIowait=$(NF-2); pctIdle=$NF}'
elif [ $FOUND_MPSTAT -eq 0 ] ; then
CMD='mpstat -P ALL 1 1'
# shellcheck disable=SC2016
FORMAT='{cpu=$(NFIELDS-10); pctUser=$(NFIELDS-9); pctNice=$(NFIELDS-8); pctSystem=$(NFIELDS-7); pctIowait=$(NFIELDS-6); pctIdle=$NF}'
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
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
assertHaveCommand "$CMD"
# shellcheck disable=SC2016
FILTER='($1=="CPU") {exit 1}'
# shellcheck disable=SC2016
FORMAT='{cpu=$1; pctUser=$(NF-4); pctNice="0"; pctSystem=$(NF-3); pctIowait=$(NF-2); pctIdle=$(NF-1)}'
elif [ "$KERNEL" = "AIX" ] ; then
queryHaveCommand mpstat
queryHaveCommand lparstat
FOUND_MPSTAT=$?
FOUND_LPARSTAT=$?
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="-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 1 1'
# shellcheck disable=SC2016
FORMAT='BEGIN {flag = 0}
{
if($0 ~ /System configuration|^$/) {next}
if(flag == 1)
{
# Prepend extra field values from lparstat
for(i=NF+4; i>=4; i--)
{
$i = $(i-3);
}
if($0 ~ /ALL/)
{
$1 = CPUPool;
$2 = OnlineVirtualCPUs;
$3 = EntitledCapacity;
}
else
{
$1 = "-";
$2 = "-";
$3 = "-";
}
}
if($0 ~ /cpu /)
{
# Prepend extra field headers from lparstat
for(i=NF+4; i>=4; i--)
{
$i = $(i-3);
}
$1 = "CPUPool";
$2 = "OnlineVirtualCPUs";
$3 = "EntitledCapacity";
flag = 1;
}
for(i=1; i<=NF; i++)
{
printf "%17s ", $i;
}
print "";
}'
fi
$CMD | tee "$TEE_DEST" | $AWK $DEFINE "$FORMAT"
echo "Cmd = [$CMD]; | $AWK $DEFINE '$FORMAT'" >> "$TEE_DEST"
exit
elif [ "$KERNEL" = "Darwin" ] ; then
HEADER='CPU pctUser pctSystem pctIdle'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='{printf "%-3s %9s %9s %9s \n", cpu, pctUser, pctSystem, pctIdle}'
# top command here is used to get a single instance of cpu metrics
CMD='top -l 1'
assertHaveCommand "$CMD"
# FILTER here skips all the rows that doesn't match "CPU".
# shellcheck disable=SC2016
FILTER='($1 !~ "CPU") {next;}'
# FORMAT here removes '%'in the end of the metrics.
# shellcheck disable=SC2016
FORMAT='function remove_char(string, char_to_remove) {
sub(char_to_remove, "", string);
return string;
}
{
cpu="all";
pctUser = remove_char($3, "%");
pctSystem = remove_char($5, "%");
pctIdle = remove_char($7, "%");
}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
CMD='eval top -P -d2 c; top -d2 c'
assertHaveCommand "$CMD"
# shellcheck disable=SC2016
FILTER='($1 !~ "CPU") { next; }'
# shellcheck disable=SC2016
FORMAT='function remove_char(string, char_to_remove) {
sub(char_to_remove, "", string);
return string;
}
{
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";
}'
elif [ "$KERNEL" = "HP-UX" ] ; then
queryHaveCommand sar
FOUND_SAR=$?
if [ $FOUND_SAR -eq 0 ] ; then
CMD='sar -M 1 1 ALL'
fi
FILTER='/HP-UX|^$|%/ {next}'
# shellcheck disable=SC2016
FORMAT='{k=0; if(5<NF) k=1} {cpu=$(1+k); pctUser=$(2+k); pctNice="0"; pctSystem=$(3+k); pctIowait=$(4+k); pctIdle=$(5+k)}'
fi
$CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $FILTER $FORMAT $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $FILTER $FORMAT $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"

211
bin/cpu_metric.sh Executable file
View file

@ -0,0 +1,211 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER='CPU pctUser pctNice pctSystem pctIowait pctIdle OSName OS_version IP_address'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='{printf "%-3s %9s %9s %9s %9s %9s %-35s %15s %-16s\n", cpu, pctUser, pctNice, pctSystem, pctIowait, pctIdle, OSName, OS_version, IP_address}'
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=$(hostname -I | cut -d\ -f1)"
else
DEFINE="-v OSName=$(cat /etc/*release | grep '\bNAME=' | cut -d '=' -f2 | tr ' ' '_' | cut -d\" -f2) -v OS_version=$(cat /etc/*release | grep '\bVERSION_ID=' | cut -d '=' -f2 | cut -d\" -f2) -v IP_address=$(hostname -I | cut -d\ -f1)"
fi
if [ $FOUND_SAR -eq 0 ] ; then
CMD='sar -P ALL 1 1'
# shellcheck disable=SC2016
FORMAT='{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 1 1'
# shellcheck disable=SC2016
FORMAT='{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
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='{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 1 1'
# shellcheck disable=SC2016
FORMAT='BEGIN {flag = 0}
{
if($0 ~ /System configuration|^$/) {next}
if(flag == 1)
{
for(i=NF+7; i>=7; i--)
{
$i = $(i-6);
}
# Prepend OSName, OS_version, IP_address values
$1 = OSName;
$2 = OSVersion/1000;
$3 = IP_address;
# Prepend lparstat field values
if($0 ~ /ALL/)
{
$4 = CPUPool;
$5 = OnlineVirtualCPUs;
$6 = EntitledCapacity;
}
else
{
$4 = "-";
$5 = "-";
$6 = "-";
}
}
if($0 ~ /cpu /)
{
for(i=NF+7; i>=7; i--)
{
$i = $(i-6);
}
# Prepend OSName, OS_version, IP_address headers
$1 = "OSName";
$2 = "OS_version";
$3 = "IP_address";
# Prepend lparstat field headers
$4 = "CPUPool";
$5 = "OnlineVirtualCPUs";
$6 = "EntitledCapacity";
flag = 1;
}
for(i=1; i<=NF; i++)
{
printf "%17s ", $i;
}
print "";
}'
fi
$CMD | tee "$TEE_DEST" | $AWK $DEFINE $DEFINE_LPARSTAT_FIELDS "$FORMAT $FILL_DIMENSIONS"
echo "Cmd = [$CMD]; | $AWK $DEFINE $DEFINE_LPARSTAT_FIELDS '$FORMAT $FILL_DIMENSIONS'" >>"$TEE_DEST"
exit
elif [ "$KERNEL" = "Darwin" ] ; then
HEADER='CPU pctUser pctSystem pctIdle OSName OS_version IP_address'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='{printf "%-3s %9s %9s %9s %-35s %15s %-16s\n", cpu, pctUser, pctSystem, pctIdle, OSName, OS_version, IP_address}'
# top command here is used to get a single instance of cpu metrics
CMD='top -l 1'
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 remove_char(string, char_to_remove) {
sub(char_to_remove, "", string);
return string;
}
{
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" = "FreeBSD" ] ; then
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;
}
{
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;
}'
elif [ "$KERNEL" = "HP-UX" ] ; then
queryHaveCommand sar
FOUND_SAR=$?
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)"
if [ $FOUND_SAR -eq 0 ] ; then
CMD='sar -M 1 1 ALL'
fi
FILTER='/HP-UX|^$|%/ {next}'
# shellcheck disable=SC2016
FORMAT='{k=0; if(5<NF) k=1} {cpu=$(1+k); pctUser=$(2+k); pctNice="0"; pctSystem=$(3+k); pctIowait=$(4+k); pctIdle=$(5+k); 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"
echo "Cmd = [$CMD]; | $AWK $DEFINE '$HEADERIZE $FILTER $FORMAT $FILL_DIMENSIONS $PRINTF' header=\"$HEADER\"" >>"$TEE_DEST"

318
bin/df.sh Executable file
View file

@ -0,0 +1,318 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
# jscpd:ignore-start
if [ "$KERNEL" = "Linux" ] ; then
assertHaveCommand df
CMD='df -h --output=source,fstype,size,used,avail,pcent,itotal,iused,iavail,ipcent,target'
# shellcheck disable=SC2016
BEGIN='BEGIN { OFS = "\t" }'
# shellcheck disable=SC2016
FILTER_POST='/(devtmpfs|tmpfs)/ {next}'
# shellcheck disable=SC2016
PRINTF='
{
if($0 ~ /^Filesystem.*/){
sub("Mounted on","MountedOn",$0);
}
match($0,/^(.*[^ ]) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+%|-) +(.*)$/,a);
if (length(a) != 0)
{ printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11];}
}'
elif [ "$KERNEL" = "SunOS" ] ; then
assertHaveCommandGivenPath /usr/bin/df
CMD_1='eval /usr/bin/df -n ; /usr/bin/df -g'
CMD_2='/usr/bin/df -h'
# shellcheck disable=SC2016
BEGIN='BEGIN { OFS = "\t" }'
#Filters out Inode info from df -g output -> inodes = Value just before "total files" & ifree = Value just before "free files"
# shellcheck disable=SC2016
INODE_FILTER='
/^\// {key=$1}
{
for(i=1;i<=NF;i++)
{
if($i == "total" && $(i+1) == "files")
{
inodes=$(i-1)
}
if($i == "free" && $(i+1) == "files")
{
ifree=$(i-1)
}
}
}
{if(NR%5==0) sub("\\(.*\\)?", "", key); print "INODE:" key, inodes, ifree}'
CMD="${CMD_1} | ${AWK} '${INODE_FILTER}'; ${CMD_2}"
FILTER_PRE='/libc_psr/ {next}'
#Maps fsType and inode info from the output of INODE_FILTER
# shellcheck disable=SC2016
MAP_FS_TO_TYPE='/INODE:/ {MoInodes[$1] = $2; MoIFree[$1] = $3;} /: / {
for(i=1;i<=NF;i++){
if($i ~ /^\/.*/)
keyCol=i;
else if($i ~ /[a-zA-Z0-9]/)
valueCol=i;
}
if($keyCol ~ /^\/.*:/)
fsTypes[substr($keyCol,1,length($keyCol)-1)] = $valueCol;
else
fsTypes[$keyCol]=$valueCol;
}'
#Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
# shellcheck disable=SC2016
PRINTF='
{
if($0 ~ /^Filesystem.*/){
for(i=1;i<=NF;i++){
if($i=="Mounted" && $(i+1)=="on"){
mountedCol=i;
sub("Mounted on","MountedOn",$0);
}
}
$(NF+1)="Type";
$(NF+1)="INodes";
$(NF+1)="IUsed";
$(NF+1)="IFree";
$(NF+1)="IUsePct";
print $0;
}
}
{
for(i=1;i<=NF;i++)
{
if($i ~ /^\/\S*/ && i==mountedCol && !(fsTypes[$mountedCol]~/(devfs|ctfs|proc|mntfs|objfs|lofs|fd|tmpfs)/) && !($0 ~ /.*\/proc.*/)){
$(NF+1)=fsTypes[$mountedCol];
$(NF+1)=MoInodes["INODE:"$mountedCol];
$(NF+1)=MoInodes["INODE:"$mountedCol]-MoIFree["INODE:"$mountedCol];
$(NF+1)=MoIFree["INODE:"$mountedCol];
if(MoInodes["INODE:"$mountedCol]>0)
{
$(NF+1)=int(((MoInodes["INODE:"$mountedCol]-MoIFree["INODE:"$mountedCol])*100)/MoInodes["INODE:"$mountedCol])"%";
}
else
{
$(NF+1)="0";
}
print $0;
}
}
}'
elif [ "$KERNEL" = "AIX" ] ; then
assertHaveCommandGivenPath /usr/bin/df
CMD='eval /usr/sysv/bin/df -n ; /usr/bin/df -kP -F %u %f %z %l %n %p %m'
# Normalize Size, Used and Avail columns
# shellcheck disable=SC2016
NORMALIZE='
function fromKB(KB) {
MB = KB/1024;
if (MB<1024) return MB "M";
GB = MB/1024;
if (GB<1024) return GB "G";
TB = GB/1024; return TB "T"
}
{
if($0 ~ /^Filesystem.*/){
for(i=1;i<=NF;i++){
if($i=="1024-blocks") {sizeCol=i; sizeFlag=1;}
if($i=="Used") {usedCol=i; usedFlag=1;}
if($i=="Available") {availCol=i; availFlag=1;}
}
}
if(!($0 ~ /^Filesystem.*/) && sizeFlag==1)
$sizeCol=fromKB($sizeCol);
if(!($0 ~ /^Filesystem.*/) && usedFlag==1)
$usedCol=fromKB($usedCol);
if(!($0 ~ /^Filesystem.*/) && availFlag==1)
$availCol=fromKB($availCol);
}'
#Maps fsType
# shellcheck disable=SC2016
MAP_FS_TO_TYPE='/: / {
for(i=1;i<=NF;i++){
if($i ~ /^\/.*/)
keyCol=i;
else if($i ~ /[a-zA-Z0-9]/)
valueCol=i;
}
if($keyCol ~ /^\/.*:/)
fsTypes[substr($keyCol,1,length($keyCol)-1)] = $valueCol;
else
fsTypes[$keyCol]=$valueCol;
}'
# shellcheck disable=SC2016
BEGIN='BEGIN { OFS = "\t" }'
# Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
# shellcheck disable=SC2016
PRINTF='
{
if($0 ~ /^Filesystem.*/){
sub("%Iused","IUsePct",$0);
for(i=1;i<=NF;i++){
if($i=="Iused") iusedCol=i;
if($i=="Ifree") ifreeCol=i;
if($i=="Mounted" && $(i+1)=="on"){
mountedCol=i;
sub("Mounted on","MountedOn",$0);
}
}
$(NF+1)="Type";
$(NF+1)="INodes";
print $0;
}
}
{
for(i=1;i<=NF;i++)
{
if($i ~ /^\/\S*/ && i==mountedCol && !(fsTypes[$mountedCol]~/(devfs|ctfs|proc|mntfs|objfs|lofs|fd|tmpfs)/) && !($0 ~ /.*\/proc.*/)){
$(NF+1)=fsTypes[$mountedCol];
$(NF+1)=$iusedCol+$ifreeCol;
print $0;
}
}
}'
elif [ "$KERNEL" = "HP-UX" ] ; then
assertHaveCommand df
assertHaveCommand fstyp
CMD='df -Pk'
# shellcheck disable=SC2016
MAP_FS_TO_TYPE='{c="fstyp " $1; c | getline ft; close(c);}'
# shellcheck disable=SC2016
HEADER='Filesystem\tType\tSize\tUsed\tAvail\tUsePct\tINodes\tIUsed\tIFree\tIUsePct\tMountedOn'
# shellcheck disable=SC2016
HEADERIZE='/^Filesystem/ {print header; next}'
# shellcheck disable=SC2016
FORMAT='{size=$2; used=$3; avail=$4; usePct=$5; mountedOn=$6; $2=ft; $3=size; $4=used; $5=avail; $6=usePct; $7=mountedOn}'
# shellcheck disable=SC2016
FILTER_POST='($2 ~ /^(tmpfs)$/) {next}'
# shellcheck disable=SC2016
PRINTF='{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11}'
elif [ "$KERNEL" = "Darwin" ] ; then
assertHaveCommand mount
assertHaveCommand df
CMD='eval mount -t nocddafs,autofs,devfs,fdesc,nfs; df -h -T nocddafs,autofs,devfs,fdesc,nfs'
# shellcheck disable=SC2016
BEGIN='BEGIN { OFS = "\t" }'
#Maps fsType
# shellcheck disable=SC2016
MAP_FS_TO_TYPE='/ on / {
for(i=1;i<=NF;i++){
if($i=="on" && $(i+1) ~ /^\/.*/)
{
key=$(i+1);
}
if($i ~ /^\(/)
value=substr($i,2,length($i)-2);
}
fsTypes[key]=value;
}'
# Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
# shellcheck disable=SC2016
PRINTF='
{
if($0 ~ /^Filesystem.*/){
sub("%iused","IUsePct",$0);
for(i=1;i<=NF;i++){
if($i=="iused") iusedCol=i;
if($i=="ifree") ifreeCol=i;
if($i=="Mounted" && $(i+1)=="on"){
mountedCol=i;
sub("Mounted on","MountedOn",$0);
}
}
$(NF+1)="Type";
$(NF+1)="INodes";
print $0;
}
}
{
for(i=1;i<=NF;i++)
{
if($i ~ /^\/dev\/.*s[0-9]+$/){
sub("^/dev/", "", $i);
sub("s[0-9]+$", "", $i);
}
if($i ~ /^\/\S*/ && i==mountedCol){
$(NF+1)=fsTypes[$mountedCol];
$(NF+1)=$iusedCol+$ifreeCol;
print $0;
}
}
}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
assertHaveCommand mount
assertHaveCommand df
CMD='eval mount -t nodevfs,nonfs,noswap,nocd9660; df -ih -t nodevfs,nonfs,noswap,nocd9660'
# shellcheck disable=SC2016
BEGIN='BEGIN { OFS = "\t" }'
#Maps fsType
# shellcheck disable=SC2016
MAP_FS_TO_TYPE='/ on / {
for(i=1;i<=NF;i++){
if($i=="on" && $(i+1) ~ /^\/.*/)
{
key=$(i+1);
}
if($i ~ /^\(/)
value=substr($i,2,length($i)-2);
}
fsTypes[key]=value;
}'
# Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
# shellcheck disable=SC2016
PRINTF='
{
if($0 ~ /^Filesystem.*/){
sub("%iused","IUsePct",$0);
for(i=1;i<=NF;i++){
if($i=="iused") iusedCol=i;
if($i=="ifree") ifreeCol=i;
if($i=="Mounted" && $(i+1)=="on"){
mountedCol=i;
sub("Mounted on","MountedOn",$0);
}
}
$(NF+1)="Type";
$(NF+1)="INodes";
print $0;
}
}
{
for(i=1;i<=NF;i++)
{
if($i ~ /^\/\S*/ && i==mountedCol){
$(NF+1)=fsTypes[$mountedCol];
$(NF+1)=$iusedCol+$ifreeCol;
print $0;
}
}
}'
fi
# jscpd:ignore-end
$CMD | tee "$TEE_DEST" | $AWK "$BEGIN $HEADERIZE $FILTER_PRE $MAP_FS_TO_TYPE $FORMAT $FILTER_POST $NORMALIZE $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK '$BEGIN $HEADERIZE $FILTER_PRE $MAP_FS_TO_TYPE $FORMAT $FILTER_POST $NORMALIZE $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"

364
bin/df_metric.sh Executable file
View file

@ -0,0 +1,364 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
# shellcheck disable=SC2016
FILL_DIMENSIONS='{length(IP_address) || IP_address = "?";length(OS_version) || OS_version = "?";length(OSName) || OSName = "?";length(IPv6_Address) || IPv6_Address = "?"}'
# jscpd:ignore-start
if [ "$KERNEL" = "Linux" ] ; then
assertHaveCommand df
CMD='df -k --output=source,fstype,size,used,avail,pcent,itotal,iused,iavail,ipcent,target'
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=$(hostname -I | cut -d\ -f1) -v IPv6_Address=$(ip -6 -brief address show scope global | xargs | cut -d ' ' -f 3 | cut -d '/' -f 1)"
else
DEFINE="-v OSName=$(cat /etc/*release | grep '\bNAME=' | cut -d '=' -f2 | tr ' ' '_' | cut -d\" -f2) -v OS_version=$(cat /etc/*release | grep '\bVERSION_ID=' | cut -d '=' -f2 | cut -d\" -f2) -v IP_address=$(hostname -I | cut -d\ -f1) -v IPv6_Address=$(ip -6 -brief address show scope global | xargs | cut -d ' ' -f 3 | cut -d '/' -f 1)"
fi
BEGIN='BEGIN { OFS = "\t" }'
FORMAT='{OSName=OSName;OS_version=OS_version;IP_address=IP_address;IPv6_Address=IPv6_Address}'
# shellcheck disable=SC2016
FILTER_POST='/(devtmpfs|tmpfs)/ {next}'
# shellcheck disable=SC2016
PRINTF='
function rem_pcent(val)
{
if(substr(val, length(val), 1)=="%")
{val=substr(val, 1, length(val)-1); return val}
}
{
if($0 ~ /^Filesystem.*/){
sub("Mounted on","MountedOn",$0);
$(NF+1)="OSName";
$(NF+1)="OS_version";
$(NF+1)="IP_address";
$(NF+1)="IPv6_Address";
print $0;
}
match($0,/^(.*[^ ]) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+%|-) +(.*)$/,a);
if (length(a) != 0)
{ printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", a[1], a[2], a[3], a[4], a[5], rem_pcent(a[6]), a[7], a[8], a[9], rem_pcent(a[10]), a[11], OSName, OS_version, IP_address, IPv6_Address}
}'
elif [ "$KERNEL" = "SunOS" ] ; then
assertHaveCommandGivenPath /usr/bin/df
CMD_1='eval /usr/bin/df -n; /usr/bin/df -g'
CMD_2='/usr/bin/df -k'
#Filters out Inode info from df -g output -> inodes = Value just before "total files" & ifree = Value just before "free files"
# shellcheck disable=SC2016
INODE_FILTER='
/^\// {key=$1}
{
for(i=1;i<=NF;i++)
{
if($i == "total" && $(i+1) == "files")
{
inodes=$(i-1)
}
if($i == "free" && $(i+1) == "files")
{
ifree=$(i-1)
}
}
}
{if(NR%5==0) sub("\\(.*\\)?", "", key); print "INODE:" key, inodes, ifree}'
CMD="${CMD_1} | ${AWK} '${INODE_FILTER}'; ${CMD_2}"
# Filters have been applied to get rid of IPv6 addresses designated for special usage to extract only the global IPv6 address.
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) -v IPv6_Address=$(ifconfig -a | grep inet6 | grep -v ' ::1 ' | grep -v ' ::1/' | grep -v ' ::1%' | grep -v ' fe80::' | grep -v ' 2002::' | grep -v ' ff00::' | head -n 1 | xargs | cut -d '/' -f 1 | cut -d '%' -f 1 | cut -d ' ' -f 2)"
FILTER_PRE='/libc_psr/ {next}'
BEGIN='BEGIN { OFS = "\t" }'
#Maps fsType and inode info from the output of INODE_FILTER
# shellcheck disable=SC2016
MAP_FS_TO_TYPE='/INODE:/ {MoInodes[$1] = $2; MoIFree[$1] = $3;} /: / {
for(i=1;i<=NF;i++){
if($i ~ /^\/.*/)
keyCol=i;
else if($i ~ /[a-zA-Z0-9]/)
valueCol=i;
}
if($keyCol ~ /^\/.*:/)
fsTypes[substr($keyCol,1,length($keyCol)-1)] = $valueCol;
else
fsTypes[$keyCol]=$valueCol;
}'
#Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
# shellcheck disable=SC2016
PRINTF='
{
if($0 ~ /^Filesystem.*/){
for(i=1;i<=NF;i++){
if($i=="Mounted" && $(i+1)=="on"){
mountedCol=i;
sub("Mounted on","MountedOn",$0);
}
}
$(NF+1)="Type";
$(NF+1)="INodes";
$(NF+1)="IUsed";
$(NF+1)="IFree";
$(NF+1)="IUsePct";
$(NF+1)="OSName";
$(NF+1)="OS_version";
$(NF+1)="IP_address";
$(NF+1)="IPv6_Address";
print $0;
}
}
{
for(i=1;i<=NF;i++)
{
if($i ~ /.*\%$/)
$i=substr($i, 1, length($i)-1);
if($i ~ /^\/\S*/ && i==mountedCol && !(fsTypes[$mountedCol]~/(devfs|ctfs|proc|mntfs|objfs|lofs|fd|tmpfs)/) && !($0 ~ /.*\/proc.*/)){
$(NF+1)=fsTypes[$mountedCol];
$(NF+1)=MoInodes["INODE:"$mountedCol];
$(NF+1)=MoInodes["INODE:"$mountedCol]-MoIFree["INODE:"$mountedCol];
$(NF+1)=MoIFree["INODE:"$mountedCol];
if(MoInodes["INODE:"$mountedCol]>0)
{
$(NF+1)=int(((MoInodes["INODE:"$mountedCol]-MoIFree["INODE:"$mountedCol])*100)/MoInodes["INODE:"$mountedCol]);
}
else
{
$(NF+1)="0";
}
$(NF+1)=OSName;
$(NF+1)=OS_version;
$(NF+1)=IP_address;
$(NF+1)=IPv6_Address;
print $0;
}
}
}'
elif [ "$KERNEL" = "AIX" ] ; then
assertHaveCommandGivenPath /usr/bin/df
CMD='eval /usr/sysv/bin/df -n ; /usr/bin/df -kP -F %u %f %z %l %n %p %m'
# Filters have been applied to get rid of IPv6 addresses designated for special usage to extract only the global IPv6 address.
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) -v IPv6_Address=$(ifconfig -a | grep inet6 | grep -v ' ::1 ' | grep -v ' ::1/' | grep -v ' ::1%' | grep -v ' fe80::' | grep -v ' 2002::' | grep -v ' ff00::' | head -n 1 | xargs | cut -d '/' -f 1 | cut -d '%' -f 1 | cut -d ' ' -f 2)"
BEGIN='BEGIN { OFS = "\t" }'
#Maps fsType
# shellcheck disable=SC2016
MAP_FS_TO_TYPE='/: / {
for(i=1;i<=NF;i++){
if($i ~ /^\/.*/)
keyCol=i;
else if($i ~ /[a-zA-Z0-9]/)
valueCol=i;
}
if($keyCol ~ /^\/.*:/)
fsTypes[substr($keyCol,1,length($keyCol)-1)] = $valueCol;
else
fsTypes[$keyCol]=$valueCol;
}'
# Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
# shellcheck disable=SC2016
PRINTF='
{
if($0 ~ /^Filesystem.*/){
sub("%Iused","IUsePct",$0);
for(i=1;i<=NF;i++){
if($i=="Iused") iusedCol=i;
if($i=="Ifree") ifreeCol=i;
if($i=="Mounted" && $(i+1)=="on"){
mountedCol=i;
sub("Mounted on","MountedOn",$0);
}
}
$(NF+1)="Type";
$(NF+1)="INodes";
$(NF+1)="OSName";
$(NF+1)="OS_version";
$(NF+1)="IP_address";
$(NF+1)="IPv6_Address";
print $0;
}
}
{
for(i=1;i<=NF;i++)
{
if($i ~ /.*\%$/)
$i=substr($i, 1, length($i)-1);
if($i ~ /^\/\S*/ && i==mountedCol && !(fsTypes[$mountedCol]~/(devfs|ctfs|proc|mntfs|objfs|lofs|fd|tmpfs)/) && !($0 ~ /.*\/proc.*/)){
$(NF+1)=fsTypes[$mountedCol];
$(NF+1)=$iusedCol+$ifreeCol;
$(NF+1)=OSName;
OS_version=OSVersion/1000;
$(NF+1)=OS_version;
$(NF+1)=IP_address;
$(NF+1)=IPv6_Address;
print $0;
}
}
}'
elif [ "$KERNEL" = "HP-UX" ] ; then
assertHaveCommand df
assertHaveCommand fstyp
CMD='df -Pk'
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
HEADER='Filesystem\tType\tSize\tUsed\tAvail\tUsePct\tINodes\tIUsed\tIFree\tIUsePct\tOSName\tOS_version\tIP_address\tMountedOn'
# shellcheck disable=SC2016
HEADERIZE='/^Filesystem/ {print header; next}'
# shellcheck disable=SC2016
MAP_FS_TO_TYPE='{c="fstyp " $1; c | getline ft; close(c);}'
# shellcheck disable=SC2016
FORMAT='{size=$2; used=$3; avail=$4; usePct=$5; mountedOn=$6; $2=ft; $3=size; $4=used; $5=avail; if(substr(usePct,length(usePct),1)=="%") $6=substr(usePct, 1, length(usePct)-1); else $6=usePct; $7=mountedOn; OSName=OSName;OS_version=OS_version;IP_address=IP_address;}'
# shellcheck disable=SC2016
FILTER_POST='($2 ~ /^(tmpfs)$/) {next}'
# shellcheck disable=SC2016
PRINTF='{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, OSName, OS_version, IP_address, $11}'
elif [ "$KERNEL" = "Darwin" ] ; then
assertHaveCommand mount
assertHaveCommand df
CMD='eval mount -t nocddafs,autofs,devfs,fdesc,nfs; df -k -T nocddafs,autofs,devfs,fdesc,nfs'
# Filters have been applied to get rid of IPv6 addresses designated for special usage to extract only the global IPv6 address.
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) -v IPv6_Address=$(ifconfig -a | grep inet6 | grep -v ' ::1 ' | grep -v ' ::1/' | grep -v ' ::1%' | grep -v ' fe80::' | grep -v ' 2002::' | grep -v ' ff00::' | head -n 1 | xargs | cut -d '/' -f 1 | cut -d '%' -f 1 | cut -d ' ' -f 2)"
# shellcheck disable=SC2016
BEGIN='BEGIN { OFS = "\t" }'
#Maps fsType
# shellcheck disable=SC2016
MAP_FS_TO_TYPE='/ on / {
for(i=1;i<=NF;i++){
if($i=="on" && $(i+1) ~ /^\/.*/)
{
key=$(i+1);
}
if($i ~ /^\(/)
value=substr($i,2,length($i)-2);
}
fsTypes[key]=value;
}'
# Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
# shellcheck disable=SC2016
PRINTF='
{
if($0 ~ /^Filesystem.*/){
sub("%iused","IUsePct",$0);
for(i=1;i<=NF;i++){
if($i=="iused") iusedCol=i;
if($i=="ifree") ifreeCol=i;
if($i=="Mounted" && $(i+1)=="on"){
mountedCol=i;
sub("Mounted on","MountedOn",$0);
}
}
$(NF+1)="Type";
$(NF+1)="INodes";
$(NF+1)="OSName";
$(NF+1)="OS_version";
$(NF+1)="IP_address";
$(NF+1)="IPv6_Address";
print $0;
}
}
{
for(i=1;i<=NF;i++)
{
if($i ~ /.*\%$/)
$i=substr($i, 1, length($i)-1);
if($i ~ /^\/dev\/.*s[0-9]+$/){
sub("^/dev/", "", $i);
sub("s[0-9]+$", "", $i);
}
if($i ~ /^\/\S*/ && i==mountedCol){
$(NF+1)=fsTypes[$mountedCol];
$(NF+1)=$iusedCol+$ifreeCol;
$(NF+1)=OSName;
$(NF+1)=OS_version;
$(NF+1)=IP_address;
$(NF+1)=IPv6_Address;
print $0;
}
}
}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
assertHaveCommand mount
assertHaveCommand df
CMD='eval mount -t nodevfs,nonfs,noswap,nocd9660; df -ik -t nodevfs,nonfs,noswap,nocd9660'
# Filters have been applied to get rid of IPv6 addresses designated for special usage to extract only the global IPv6 address.
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) -v IPv6_Address=$(ifconfig -a | grep inet6 | grep -v ' ::1 ' | grep -v ' ::1/' | grep -v ' ::1%' | grep -v ' fe80::' | grep -v ' 2002::' | grep -v ' ff00::' | head -n 1 | xargs | cut -d '/' -f 1 | cut -d '%' -f 1 | cut -d ' ' -f 2)"
# shellcheck disable=SC2016
BEGIN='BEGIN { OFS = "\t" }'
#Maps fsType
# shellcheck disable=SC2016
MAP_FS_TO_TYPE='/ on / {
for(i=1;i<=NF;i++){
if($i=="on" && $(i+1) ~ /^\/.*/)
{
key=$(i+1);
}
if($i ~ /^\(/)
value=substr($i,2,length($i)-2);
}
fsTypes[key]=value;
}'
# Append Type and Inode headers to the main header and print respective fields from values stored in MAP_FS_TO_TYPE variables
# shellcheck disable=SC2016
PRINTF='
{
if($0 ~ /^Filesystem.*/){
sub("%iused","IUsePct",$0);
for(i=1;i<=NF;i++){
if($i=="iused") iusedCol=i;
if($i=="ifree") ifreeCol=i;
if($i=="Mounted" && $(i+1)=="on"){
mountedCol=i;
sub("Mounted on","MountedOn",$0);
}
}
$(NF+1)="Type";
$(NF+1)="INodes";
$(NF+1)="OSName";
$(NF+1)="OS_version";
$(NF+1)="IP_address";
$(NF+1)="IPv6_Address";
print $0;
}
}
{
for(i=1;i<=NF;i++)
{
if($i ~ /.*\%$/)
$i=substr($i, 1, length($i)-1);
if($i ~ /^\/\S*/ && i==mountedCol){
$(NF+1)=fsTypes[$mountedCol];
$(NF+1)=$iusedCol+$ifreeCol;
$(NF+1)=OSName;
$(NF+1)=OS_version;
$(NF+1)=IP_address;
$(NF+1)=IPv6_Address;
print $0;
}
}
}'
fi
# jscpd:ignore-end
# shellcheck disable=SC2086
$CMD | tee "$TEE_DEST" | $AWK $DEFINE "$BEGIN $HEADERIZE $FILTER_PRE $MAP_FS_TO_TYPE $FORMAT $FILTER_POST $NORMALIZE $FILL_DIMENSIONS $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK $DEFINE '$BEGIN $HEADERIZE $FILTER_PRE $MAP_FS_TO_TYPE $FORMAT $FILTER_POST $NORMALIZE $FILL_DIMENSIONS $PRINTF' header=\"$HEADER\"" >>"$TEE_DEST"

225
bin/hardware.sh Executable file
View file

@ -0,0 +1,225 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
# shellcheck disable=SC2016
FORMAT='{key = $1; if (NF == 1) {value = "<notAvailable>"} else {value = $2; for (i=3; i <= NF; i++) value = value " " $i}}'
PRINTF='{printf("%-20s %-s\n", key, value)}'
if [ "$KERNEL" = "Linux" ] ; then
TMP_ERROR_FILTER_FILE=$SPLUNK_HOME/var/run/splunk/unix_hardware_error_tmpfile # For filtering out lshw warning from stderr
queryHaveCommand ip
FOUND_IP=$?
# CPUs
CPU_TYPE=$(awk -F: '/model name/ {print $2; exit}' /proc/cpuinfo 2>>"$TEE_DEST")
CPU_CACHE=$(awk -F: '/cache size/ {print $2; exit}' /proc/cpuinfo 2>>"$TEE_DEST")
CPU_COUNT=$(grep -c processor /proc/cpuinfo 2>>"$TEE_DEST")
# HDs
# shellcheck disable=SC2010
for deviceBasename in $(ls /sys/block | grep -E -v '^(dm|md|ram|sr|loop)')
do
DEVICE="/sys/block/$deviceBasename" HARD_DRIVES="$HARD_DRIVES $deviceBasename"
if [ -e "$DEVICE"/device/model ] ; then HARD_DRIVES="$HARD_DRIVES ($(sed 's/ *$//' "$DEVICE"/device/model))"; fi
if [ -e "$DEVICE"/size ] ; then HARD_DRIVES="$HARD_DRIVES $((($(cat "$DEVICE"/size)*512)/(1024*1024*1024))) GB; "; fi
done
# NICs
# For Ubuntu version >= 20, we use cat to read the dmseg file. Otherwise we use dmesg cmd.
OS_FILE=/etc/os-release
if [ -f /proc/sys/kernel/dmesg_restrict ]; then
DMESG_RESTRICT_VALUE=$(cat "/proc/sys/kernel/dmesg_restrict" 2>/dev/null)
else
DMESG_RESTRICT_VALUE=1
fi
if echo "$OS_ID" | grep -qi suse; then
assertHaveCommandGivenPath /usr/sbin/hwinfo
NIC_TYPE=$(/usr/sbin/hwinfo --netcard --short | awk '{$1=""; sub(/^ */, "", $0); print $0}')
elif [ -e "$DMESG_FILE" ] && [ "$UBUNTU_MAJOR_VERSION" -ge 20 ] ; then
NIC_TYPE=$(cat "$DMESG_FILE" | awk '/Ethernet/ {sub("[^a-zA-Z]*Ethernet.*$", ""); sub("^[^:]*: ", ""); print; exit}')
elif [ $DMESG_RESTRICT_VALUE -eq 0 ] ; then
NIC_TYPE=$(dmesg | awk '/Ethernet/ {sub("[^a-zA-Z]*Ethernet.*$", ""); sub("^[^:]*: ", ""); print; exit}')
else
NIC_TYPE=""
fi
if [ -z "$NIC_TYPE" ] ; then
assertHaveCommand lshw
PARSE_1='/^\s+product: / {
product = $2;
for (i=3; i<=NF; i++) product = product " " $i
}
/^\s+vendor: / {
vendor = $2;
for (i=3; i<=NF; i++) vendor = vendor " " $i
printf "%s, %s\n", vendor, product;
exit
}'
NIC_TYPE=$(lshw -class network 2>$TMP_ERROR_FILTER_FILE | awk "$PARSE_1")
# shellcheck disable=SC2086
grep -v "you should run this program as super-user" < $TMP_ERROR_FILTER_FILE 1>&2
# shellcheck disable=SC2086
rm $TMP_ERROR_FILTER_FILE 2>/dev/null
fi
if [ $FOUND_IP -eq 0 ]; then
NIC_COUNT=$(ip a | awk '!length() || $2 ~/lo/ || /^ / {next} {ct++} END {print ct}')
else
assertHaveCommand ifconfig
NIC_COUNT=$(ifconfig | awk '!length() || /^( |lo)/ {next} {ct++} END {print ct}')
fi
# memory
MEMORY_REAL=$(awk -F: '/MemTotal/ {print $2; exit}' /proc/meminfo 2>>"$TEE_DEST")
MEMORY_SWAP=$(awk -F: '/SwapTotal/ {print $2; exit}' /proc/meminfo 2>>"$TEE_DEST")
elif [ "$KERNEL" = "SunOS" ] ; then
UNAME_PLATFORM=$(uname -i)
assertHaveCommand mpstat
assertHaveCommand iostat
assertHaveCommand dmesg
assertHaveCommandGivenPath /usr/sbin/prtconf
assertHaveCommandGivenPath /usr/sbin/swap
# CPUs and NIC count
if [ -x /usr/sbin/prtdiag ] ; then
if [ "$SOLARIS_10" = "true" ] || [ "$SOLARIS_11" = "true" ] ; then
# shellcheck disable=SC2016
CPU_TYPE=$(/usr/sbin/prtdiag | $AWK 'BEGIN {leftToSkip=-1} /Processor Sockets/ {leftToSkip=3; next} (leftToSkip>0) {leftToSkip-=1; next} (!leftToSkip) {sub("[0-9]$", "", $0); sub(" CPU socket #$", "", $0); print $0; exit}')
else
# shellcheck disable=SC2016
CPU_TYPE=$(/usr/sbin/prtdiag | $AWK 'BEGIN {leftToSkip=-1} /Processor Sockets/ {leftToSkip=3; next} (leftToSkip>0) {leftToSkip-=1; next} (!leftToSkip) {sub("[0-9]$", "", $0); sub(" [A-Za-z]+ ?$", "", $0); print $0; exit}')
fi
NIC_COUNT=$(/usr/sbin/prtdiag | grep -c NIC)
elif [ -x /usr/platform/"$UNAME_PLATFORM"/sbin/prtdiag ]; then
# shellcheck disable=SC2016
CPU_TYPE=$(/usr/platform/"$UNAME_PLATFORM"/sbin/prtdiag | $AWK 'BEGIN {leftToSkip=-1} /Processor Sockets/ {leftToSkip=3; next} (leftToSkip>0) {leftToSkip-=1; next} (!leftToSkip) {sub("[0-9]$", "", $0); sub(" [A-Za-z]+ ?$", "", $0); print $0; exit}')
NIC_COUNT=$(/usr/platform/"$UNAME_PLATFORM"/sbin/prtdiag | grep -c NIC)
else
echo "Not found commandGivenPath [ /usr/sbin/prtdiag or /usr/platform/$UNAME_PLATFORM/sbin/prtdiag ] on this host, quitting" >> "$TEE_DEST"
exit 1
fi
# shellcheck disable=SC2016
CPU_CACHE=$(/usr/sbin/prtconf -v | $AWK 'function hexToDecKB (hex, digitsAll, idx, curDigit, dec) {sub("^value=", "", hex); for (idx=1; idx<=length(hex); idx++) {curDigit = index("0123456789abcdef", substr(hex,idx,1)); dec=(16*dec)+curDigit-1} if (debug) printf "hexToDec:%s->%d ", hex, dec; dec /= 1024; return dec} BEGIN {L2=L1i=L1d=0} (L2) {strL2=$1; L2=0} /l2-cache-size/ {L2=1} (L1i) {strL1i=$1; L1i=0} /l1-icache-size/ {L1i=1} (L1d) {strL1d=$1; L1d=0} /l1-dcache-size/ {L1d=1} END {if (debug) printf "strL2:%s strL1i:%s strL1d:%s ", strL2, strL1i, strL1d; nL2=hexToDecKB(strL2); nL1=hexToDecKB(strL1i)+hexToDecKB(strL1d); printf "L1:%dKB L2:%dKB", nL1, nL2}' debug="$DEBUG")
if [ "$SOLARIS_8" = "true" ] || [ "$SOLARIS_9" = "true" ] ; then
CPU_COUNT=$(mpstat | grep -cv CPU)
else
CPU_COUNT=$(mpstat -q | grep -cv CPU)
fi
# # # that gives # of cores; `/usr/sbin/psrinfo -p` gives # of chips
# HDs
# shellcheck disable=SC2016
HARD_DRIVES=$(iostat -E | $AWK '/Soft Errors:/ {name=$1} /^Vendor:/ {info = $2 " " $4} /^Size:/ {sizeGB=0+$2; if (sizeGB>0) drives[name]=info " " $2} END {for (d in drives) printf("%s %s; ", d, drives[d])}')
# NICs
NIC_TYPE=$(dmesg | grep 'mac address' | sed -n 's/^.*] [a-z]*[0-9]*: //;s/mac address .*$//;p' | uniq)
# memory
MEMORY_REAL=$(/usr/sbin/prtconf | awk '/^Memory size:/ {print $3 " MB"; exit}')
# shellcheck disable=SC2016
MEMORY_SWAP=$(/usr/sbin/swap -s | $AWK '{used=0+$(NF-3); free=0+$(NF-1); total=(used+free)/1024; print int(total) " MB"}')
elif [ "$KERNEL" = "AIX" ] ; then
assertHaveCommandGivenPath /usr/sbin/prtconf
assertHaveCommandGivenPath /usr/sbin/lsattr
assertHaveCommandGivenPath /usr/sbin/lsdev
assertHaveCommandGivenPath /usr/sbin/lscfg
assertHaveCommandGivenPath /usr/sbin/lspv
assertHaveCommandGivenPath /usr/sbin/lsps
# CPUs
# shellcheck disable=SC2016
CPU_TYPE=$(/usr/sbin/prtconf | $AWK -F: '/^Processor Type:/{type=$2} /^Processor Clock Speed:/ {clock=$2}END {printf("%s %s",type,clock)}')
# shellcheck disable=SC2016
CPU_CACHE=$(/usr/sbin/lsattr -EHl L2cache0 | $AWK '/^size/{print "L2:" $2 " KB" }')
CPU_COUNT=$(/usr/sbin/lsdev -Cc processor | grep -c proc)
# HDs
HDD_NAME=$(/usr/sbin/lsdev -Cc disk | awk '{print $1}')
HARD_DRIVES=""
for disk in $HDD_NAME
do
# shellcheck disable=SC2016
HARD_INFO=$(/usr/sbin/lscfg -vpl "$disk" | $AWK -F . '/Manufacturer/ {name = $NF } /Machine Type and Model/ {info = $(NF)} END {printf("%s %s", name, info)}')
ACTIVE_STATUS=$(/usr/sbin/lspv | awk -v pat="$disk" '$0~pat{print $NF}')
VOLUME_GROUP=$(/usr/sbin/lspv | awk -v pat="$disk" '$0~pat{print $3}')
if [ "${ACTIVE_STATUS}" != "active" ] || [ "${VOLUME_GROUP}" = "None" ]; then # lspv cannot get disk-size as disk is inactive or not in any volume group
HARD_MB=$(getconf DISK_SIZE /dev/"$disk")" MB"
else
HARD_MB=$(/usr/sbin/lspv -L "$disk" | awk -F \( '{print $2}'| awk '/VG DESCRIPTORS/{print $1" MB"}')
fi
HARD_DRIVES="$HARD_DRIVES$disk $HARD_INFO $HARD_MB; "
done
# NICs
NIC_TYPE=$(/usr/sbin/lsdev -Cc adapter | grep ent | awk -F" " '{print $1" "$3"; "}')
NIC_COUNT=$(/usr/sbin/lsdev -Cc adapter | grep -c ent)
# memory
# shellcheck disable=SC2016
MEMORY_REAL=$(/usr/sbin/lsattr -EHl mem0 | $AWK '/^size/ {print $2 " MB"}')
# shellcheck disable=SC2016
MEMORY_SWAP=$(/usr/sbin/lsps -s | $AWK -F MB '/MB/ {print $1" MB"}')
elif [ "$KERNEL" = "Darwin" ] ; then
assertHaveCommand sysctl
assertHaveCommand df
assertHaveCommand system_profiler
assertHaveCommand ifconfig
# CPUs
CPU_TYPE=$(sysctl machdep.cpu.brand_string | sed -E 's/^.*: //;s/[ ]+/ /g')
CPU_CACHE=$(sysctl hw.cachesize | awk '{L1=$3/1024; L2=$4/(1024*1024); printf "L1:%d KB; L2:%d MB", L1, L2}')
CPU_COUNT=$(sysctl hw.ncpu | sed 's/^.*: //')
# HDs
HARD_DRIVES=$(df -h | awk '/^\/dev/ {sub("^.*\134/", "", $1); drives[$1] = $2} END {for(d in drives) printf("%s: %s; ", d, drives[d])}')
# NICs
NIC_TYPE=$(system_profiler SPNetworkDataType | awk '/Media Subtype:/ {print $3; exit}')
NIC_COUNT=$(ifconfig | grep -c 'supported media:.*baseT')
# memory
MEMORY_REAL=$(sysctl hw.memsize | awk '{print $2/(1024*1024) " MB"}')
MEMORY_SWAP=$(sysctl vm.swapusage | awk '{print 0+$4 " MB"}')
elif [ "$KERNEL" = "HP-UX" ] ; then
assertHaveCommand ioscan
assertHaveCommand iostat
assertHaveCommand lanscan
assertHaveCommand machinfo
assertHaveCommand swapinfo
OUTPUT=$(machinfo)
CPU_TYPE=$(echo "$OUTPUT" | awk '/processor family/ { for(i=4; i<=NF; i++) printf("%s ", $i); exit}')
CPU_CACHE=$(echo "$OUTPUT" | awk '/L[123]/ {cache+=$5} END {print cache " KB"}')
CPU_COUNT=$(echo "$OUTPUT" | awk '/CPUs/ {print $5; exit}')
HARD_DRIVES=$(iostat 2 1 | wc -l)
# shellcheck disable=SC2307,2003
HARD_DRIVES=$(expr "$HARD_DRIVES"-4)
NIC_COUNT=$(lanscan -i | wc -l)
NIC_TYPE=$(ioscan -u | grep lan | awk 'NF>2 {for(i=3; i<=NF; i++) printf("%s", $i); exit}')
OUTPUT=$(swapinfo -tm)
MEMORY_REAL=$(echo "$OUTPUT" | awk '$1=="memory" {print $2 " MB"; exit}')
MEMORY_SWAP=$(echo "$OUTPUT" | awk '$1=="dev" {print $2 " MB"; exit}')
elif [ "$KERNEL" = "FreeBSD" ] ; then
assertHaveCommand sysctl
assertHaveCommand df
assertHaveCommand ifconfig
assertHaveCommand dmesg
assertHaveCommand top
# CPUs
CPU_TYPE=$(sysctl hw.model | sed 's/^.*: //')
CPU_CACHE=
CPU_COUNT=$(sysctl hw.ncpu | sed 's/^.*: //')
# HDs
HARD_DRIVES=$(df -h | awk '/^\/dev/ {sub("^.*\134/", "", $1); drives[$1] = $2} END {for(d in drives) printf("%s: %s; ", d, drives[d])}')
# NICs
IFACE_NAME=$(ifconfig -a | awk '!/^[a-z]/ {next} /LOOPBACK/ {next} {print $1}' | head -1)
NIC_TYPE=$(dmesg | awk '(index($0, iface) && index($0, " port ")) {sub("^.*<", ""); sub(">.*$", ""); print $0}' iface="$IFACE_NAME" | head -1)
NIC_COUNT=$(ifconfig -a | grep -c media)
# memory
MEMORY_REAL=$(sysctl hw.physmem | awk '{print $2/(1024*1024) "MB"}')
MEMORY_SWAP=$(top -Sb 0 | awk '/^Swap: / {print $2 "B"}')
fi
formatAndPrint ()
{
# shellcheck disable=SC2086
echo $1 | awk "$FORMAT $PRINTF"
}
formatAndPrint "KEY VALUE"
formatAndPrint "CPU_TYPE $CPU_TYPE"
formatAndPrint "CPU_CACHE $CPU_CACHE"
formatAndPrint "CPU_COUNT $CPU_COUNT"
formatAndPrint "HARD_DRIVES $HARD_DRIVES"
formatAndPrint "NIC_TYPE $NIC_TYPE"
formatAndPrint "NIC_COUNT $NIC_COUNT"
formatAndPrint "MEMORY_REAL $MEMORY_REAL"
formatAndPrint "MEMORY_SWAP $MEMORY_SWAP"

528
bin/interfaces.sh Executable file
View file

@ -0,0 +1,528 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# jscpd:ignore-start
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER='Name MAC inetAddr inet6Addr Collisions RXbytes RXerrors TXbytes TXerrors Speed Duplex'
FORMAT='{mac = length(mac) ? mac : "?"; collisions = length(collisions) ? collisions : "?"; RXbytes = length(RXbytes) ? RXbytes : "?"; RXerrors = length(RXerrors) ? RXerrors : "?"; TXbytes = length(TXbytes) ? TXbytes : "?"; TXerrors = length(TXerrors) ? TXerrors : "?"; speed = length(speed) ? speed : "?"; duplex = length(duplex) ? duplex : "?"}'
PRINTF='END {printf "%-10s %-17s %-15s %-42s %-10s %-16s %-16s %-16s %-16s %-12s %-12s\n", name, mac, IPv4, IPv6, collisions, RXbytes, RXerrors, TXbytes, TXerrors, speed, duplex}'
if [ "$KERNEL" = "Linux" ] ; then
OS_FILE=/etc/os-release
HEADER='Name MAC inetAddr inet6Addr Collisions RXbytes RXerrors RXdropped TXbytes TXerrors TXdropped Speed Duplex'
PRINTF='END {printf "%-10s %-17s %-15s %-42s %-10s %-16s %-16s %-18s %-16s %-16s %-18s %-12s %-12s\n", name, mac, IPv4, IPv6, collisions, RXbytes, RXerrors, RXdropped, TXbytes, TXerrors, TXdropped, speed, duplex}'
queryHaveCommand ip
FOUND_IP=$?
if [ $FOUND_IP -eq 0 ]; then
CMD_LIST_INTERFACES="eval ip -s a | tee $TEE_DEST|grep 'state UP' | grep mtu | grep -Ev lo | tee -a $TEE_DEST | cut -d':' -f2 | tee -a $TEE_DEST | cut -d '@' -f 1 | tee -a $TEE_DEST | sort -u | tee -a $TEE_DEST"
# shellcheck disable=SC2016
CMD='eval ip addr show $iface; ip -s link show'
# shellcheck disable=SC2016
GET_IPv4='{if ($0 ~ /inet /) {split($2, a, " "); IPv4 = a[1]}}'
# shellcheck disable=SC2016
GET_IPv6='{if ($0 ~ /inet6 /) { IPv6 = $2 }}'
# shellcheck disable=SC2016
GET_TXbytes='{
if($0 ~ /TX: /){
tx_row_count=NR+1;
for(i=1;i<=NF;i++){
if($i=="bytes"){
TX_bytes_column=i;
}
else if($i=="errors"){
TX_errors_column=i;
}
else if($i=="dropped"){
TX_dropped_column=i;
}
else if($i=="collsns"){
TX_collsns_column=i;
}
}
next;
}
if(NR==tx_row_count){
(TX_bytes_column == "") ? TXbytes = 0 : TXbytes = $(TX_bytes_column - 1);
(TX_errors_column == "") ? TXerrors = "<n/a>" : TXerrors = $(TX_errors_column - 1);
(TX_dropped_column == "") ? TXdropped = "<n/a>" : TXdropped = $(TX_dropped_column - 1);
(TX_collsns_column == "") ? collisions = 0 : collisions = $(TX_collsns_column - 1);
}
}'
# shellcheck disable=SC2016
GET_RXbytes='{
if($0 ~ /RX: /){
rx_row_count=NR+1;
for(i=1;i<=NF;i++){
if($i=="bytes"){
RX_bytes_column=i;
}
else if($i=="errors"){
RX_errors_column=i;
}
else if($i=="dropped"){
RX_dropped_column=i;
}
}next;
}
if(NR==rx_row_count){
(RX_bytes_column == "") ? RXbytes = 0 : RXbytes = $(RX_bytes_column - 1);
(RX_errors_column == "") ? RXerrors = "<n/a>" : RXerrors = $(RX_errors_column - 1);
(RX_dropped_column == "") ? RXdropped = "<n/a>" : RXdropped = $(RX_dropped_column - 1);
}
}'
else
assertHaveCommand ifconfig
# shellcheck disable=SC2089
CMD_LIST_INTERFACES="eval ifconfig | tee $TEE_DEST | grep 'Link encap:\|mtu' | grep -Ev lo | tee -a $TEE_DEST | cut -d' ' -f1 | cut -d':' -f1 | tee -a $TEE_DEST | sort -u | tee -a $TEE_DEST"
CMD='ifconfig'
# shellcheck disable=SC2016
GET_IPv4='{if ($0 ~ /inet addr:/) {split($2, a, ":"); IPv4 = a[2]} else if ($0 ~ /inet /) {IPv4 = $2}}'
# shellcheck disable=SC2016
GET_IPv6='{if ($0 ~ /inet6 addr:/) { IPv6 = $3 } else if ($0 ~ /inet6 /) { IPv6 = $2 }}'
# shellcheck disable=SC2016
GET_COLLISIONS='{
if ($0 ~ /collisions:/){
for(i=1;i<=NF;i++){
if($i ~ /collisions:/){
collisions_col_no = i;
break;
}
}
if(collisions_col_no==""){
collisions=0;
}
else
split($collisions_col_no, a, ":");
collisions=a[2];
}
else if($0 ~ /collisions /){
for(i=1;i<=NF;i++){
if($i=="collisions"){
collisions_column=i+1;
}
}
(collisions_column != "") ? collisions = $collisions_column : collisions = 0;
}
}'
# shellcheck disable=SC2016
GET_RXbytes='{
if ($0 ~ /RX bytes:/){
for(i=1;i<=NF;i++){
if($i ~ /bytes:/){
rxbytes_col_no = i;
break;
}
}
if(rxbytes_col_no==""){
RXbytes=0;
}
else
split($rxbytes_col_no, a, ":");
RXbytes=a[2];
}
else if($0 ~ /RX/ && $0 ~ /bytes/){
for(i=1;i<=NF;i++){
if($i=="bytes"){
RXbytes_column=i+1;
row = NR;
}
}
if(NR == row){
if(RXbytes_column != ""){
RXbytes = $RXbytes_column;
}
else
RXbytes = 0;
}
}
}'
# shellcheck disable=SC2016
GET_RXerrors='{
if ($0 ~ /RX packets:/){
for(i=1;i<=NF;i++){
if($i ~ /errors:/){
rxerrors_col_no = i;
}
else if($i ~ /dropped:/){
rxdropped_col_no = i;
}
}
if(rxerrors_col_no != ""){
split($rxerrors_col_no, a, ":");
RXerrors=a[2];
}
else
RXerrors="<n/a>";
if(rxdropped_col_no != ""){
split($rxdropped_col_no, b, ":");
RXdropped=b[2];
}
else
RXdropped="<n/a>";
}
else if($0 ~ /RX/ && ($0 ~ /errors/)){
for(i=1;i<=NF;i++){
if($i=="errors"){
RXerrors_column=i+1;
}
if($i=="dropped"){
RXdropped_column=i+1;
}
}
(RXerrors_column != "") ? RXerrors=$RXerrors_column : RXerrors = "<n/a>";
(RXdropped_column != "") ? RXdropped = $RXdropped_column : RXdropped = "<n/a>";
}
}'
# shellcheck disable=SC2016
GET_TXbytes='{
if ($0 ~ /TX bytes:/){
for(i=1;i<=NF;i++){
if($i ~ /bytes:/){
txbytes_col_no = i;
}
}
if(txbytes_col_no==""){
TXbytes=0;
}
else
split($txbytes_col_no, a, ":");
TXbytes=a[2];
}
else if($0 ~ /TX/ && $0 ~ /bytes/){
for(i=1;i<=NF;i++){
if($i=="bytes"){
TXbytes_column=i+1;
row = NR;
}
}
if(NR == row){
if(TXbytes_column != ""){
TXbytes = $TXbytes_column;
}
else
TXbytes = 0;
}
}
}'
# shellcheck disable=SC2016
GET_TXerrors='{
if ($0 ~ /TX packets:/){
for(i=1;i<=NF;i++){
if($i ~ /errors:/){
txerrors_col_no = i;
}
if($i ~ /dropped:/){
txdropped_col_no = i;
}
}
if(txerrors_col_no != ""){
split($txerrors_col_no, a, ":");
TXerrors=a[2];
}
else
TXerrors="<n/a>";
if(txdropped_col_no != ""){
split($txdropped_col_no, b, ":");
TXdropped=b[2];
}
else
TXdropped="<n/a>";
}
else if($0 ~ /TX/ && $0 ~ /errors/){
for(i=1;i<=NF;i++){
if($i=="errors"){
TXerrors_column=i+1;
}
if($i=="dropped"){
TXdropped_column=i+1;
}
}
(TXerrors_column != "") ? TXerrors = $TXerrors_column : TXerrors = "<n/a>";
(TXdropped_column != "") ? TXdropped = $TXdropped_column : TXdropped = "<n/a>";
}
}'
fi
GET_ALL="$GET_IPv4 $GET_IPv6 $GET_COLLISIONS $GET_RXbytes $GET_RXerrors $GET_TXbytes $GET_TXerrors"
FILL_BLANKS='{length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>"; length(TXdropped) || TXdropped = "<n/a>";length(RXdropped) || RXdropped = "<n/a>"; length(IPv4) || IPv4 = "<n/a>"; length(IPv6) || IPv6= "<n/a>"}'
BEGIN='BEGIN {RXbytes = TXbytes = collisions = 0}'
# shellcheck disable=SC2090
out=$($CMD_LIST_INTERFACES)
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
fi
for iface in $out
do
if [ -r /sys/class/net/"$iface"/duplex ]; then
DUPLEX=$(cat /sys/class/net/"$iface"/duplex 2>/dev/null || echo 'error')
if [ "$DUPLEX" != 'error' ]; then
DUPLEX=$(echo "$DUPLEX" | sed 's/./\u&/')
if [ -r /sys/class/net/"$iface"/speed ]; then
SPEED=$(cat /sys/class/net/"$iface"/speed 2>/dev/null || echo 'error')
[ -n "$SPEED" ] && [ "$SPEED" != 'error' ] && SPEED="${SPEED}Mb/s"
else
# For SLES, making use of ethtool as dmesg requires root privilege.
if echo "$OS_ID" | grep -qi suse; then
assertHaveCommandGivenPath /usr/sbin/ethtool
SPEED=$(/usr/sbin/ethtool $iface 2>/dev/null | awk '/Speed: +[0-9]+Mb\/s/ {print gensub(/[[:space:]]*Speed: +/, "", 1)}')
# For Ubuntu version >= 20, we use cat to read the dmseg file. Otherwise we use dmesg cmd.
elif [ -e "$DMESG_FILE" ] && [ "$UBUNTU_MAJOR_VERSION" -ge 20 ] ; then
SPEED=$(cat "$DMESG_FILE"* | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([0-9]+)([Mm]bps)/)) {print $i} else { if (match($i, /[Mm]bps/)) {print $(i-1) "Mb/s"} } } }' | sed '$!d')
else
assertHaveCommand dmesg
SPEED=$(dmesg | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([0-9]+)([Mm]bps)/)) {print $i} else { if (match($i, /[Mm]bps/)) {print $(i-1) "Mb/s"} } } }' | sed '$!d')
fi
fi
else
DUPLEX=""
fi
fi
if [ "$DUPLEX" = "" ] || [ "$SPEED" = "" ] ; then
if echo "$OS_ID" | grep -qi suse; then
assertHaveCommandGivenPath /usr/sbin/ethtool
if [ "$DUPLEX" = "" ] ; then
DUPLEX=$(/usr/sbin/ethtool $iface 2>/dev/null | awk '/Duplex: +[A-Za-z]+/ {print gensub(/[[:space:]]*Duplex: +/, "", 1)}')
fi
if [ "$SPEED" = "" ] ; then
SPEED=$(/usr/sbin/ethtool $iface 2>/dev/null | awk '/Speed: +[0-9]+Mb\/s/ {print gensub(/[[:space:]]*Speed: +/, "", 1)}')
fi
else
assertHaveCommand dmesg
# Get Duplex only if still null
if [ "$DUPLEX" = "" ] ; then
# For Ubuntu version >= 20, we use cat to read the dmseg file. Otherwise we use dmesg cmd.
if [ -e "$DMESG_FILE" ] && [ "$UBUNTU_MAJOR_VERSION" -ge 20 ] ; then
DUPLEX=$(cat "$DMESG_FILE"* | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([-_a-zA-Z0-9]+)([Dd]uplex)/)) {print $i} else { if (match($i, /[Dd]uplex/)) {print $(i-1) } } } }' | sed 's/[-_]//g; $!d')
else
DUPLEX=$(dmesg | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([-_a-zA-Z0-9]+)([Dd]uplex)/)) {print $i} else { if (match($i, /[Dd]uplex/)) {print $(i-1) } } } }' | sed 's/[-_]//g; $!d')
fi
fi
# Get Speed only if still null
if [ "$SPEED" = "" ] ; then
# For Ubuntu version >= 20, we use cat to read the dmseg file. Otherwise we use dmesg cmd.
if [ -e "$DMESG_FILE" ] && [ "$UBUNTU_MAJOR_VERSION" -ge 20 ] ; then
SPEED=$(cat "$DMESG_FILE"* | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([0-9]+)([Mm]bps)/)) {print $i} else { if (match($i, /[Mm]bps/)) {print $(i-1) "Mb/s"} } } }' | sed '$!d')
else
SPEED=$(dmesg | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([0-9]+)([Mm]bps)/)) {print $i} else { if (match($i, /[Mm]bps/)) {print $(i-1) "Mb/s"} } } }' | sed '$!d')
fi
fi
fi
fi
if [ $FOUND_IP -eq 0 ]; then
# shellcheck disable=SC2016
GET_MAC='{if ($0 ~ /ether /) { mac = $2 }}'
elif [ -r /sys/class/net/"$iface"/address ]; then
MAC=$(cat /sys/class/net/"$iface"/address)
else
# shellcheck disable=SC2016
GET_MAC='{if ($0 ~ /ether /) { mac = $2; } else if ( NR == 1 ) { mac = $5; }}'
fi
if [ "$DUPLEX" != 'error' ] && [ "$SPEED" != 'error' ]; then
$CMD "$iface" | tee -a "$TEE_DEST" | awk "$BEGIN $GET_MAC $GET_ALL $FILL_BLANKS $PRINTF" name="$iface" speed="$SPEED" duplex="$DUPLEX" mac="$MAC"
echo "Cmd = [$CMD $iface]; | awk '$BEGIN $GET_MAC $GET_ALL $FILL_BLANKS $PRINTF' name=$iface speed=$SPEED duplex=$DUPLEX mac=$MAC" >> "$TEE_DEST"
else
echo "ERROR: cat command failed for interface $iface" >> "$TEE_DEST"
fi
done
elif [ "$KERNEL" = "SunOS" ] ; then
assertHaveCommandGivenPath /usr/sbin/ifconfig
assertHaveCommand kstat
# shellcheck disable=SC2089
CMD_LIST_INTERFACES="eval /usr/sbin/ifconfig -au | tee $TEE_DEST | egrep -v 'LOOPBACK|netmask' | tee -a $TEE_DEST | grep flags | cut -d':' -f1 | tee -a $TEE_DEST | sort -u | tee -a $TEE_DEST"
# shellcheck disable=SC2016
GET_COLLISIONS_RXbytes_TXbytes_SPEED_DUPLEX='($1=="collisions") {collisions=$2} ($1=="duplex" || $1=="link_duplex") {duplex=$2} ($1=="rbytes") {RXbytes=$2} ($1=="obytes") {TXbytes=$2} ($1=="ierrors") {RXerrors=$2} ($1=="oerrors") {TXerrors=$2} ($1=="ifspeed") {speed=$2; speed/=1000000; speed=speed "Mb/s"}'
# shellcheck disable=SC2016
GET_IP='/ netmask / {for (i=1; i<=NF; i++) {if ($i == "inet") IPv4 = $(i+1); if ($i == "inet6") IPv6 = $(i+1)}}'
# shellcheck disable=SC2016
GET_MAC='{if ($1 == "ether") {split($2, submac, ":"); mac=sprintf("%02s:%02s:%02s:%02s:%02s:%02s", submac[1], submac[2], submac[3], submac[4], submac[5], submac[6])}}'
FILL_BLANKS='{length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>"; IPv4 = IPv4 ? IPv4 : "<n/a>"; IPv6 = IPv6 ? IPv6 : "<n/a>"}'
GET_ALL="$GET_COLLISIONS_RXbytes_TXbytes_SPEED_DUPLEX $GET_IP $GET_MAC $FILL_BLANKS"
# shellcheck disable=SC2090
out=$($CMD_LIST_INTERFACES)
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
fi
for iface in $out
do
echo "Cmd = [$CMD_LIST_INTERFACES]" >> "$TEE_DEST"
NODE=$(uname -n)
# shellcheck disable=SC2050
if [ SOLARIS_8 = false ] && [ SOLARIS_9 = false ] ; then
CMD_DESCRIBE_INTERFACE="eval kstat -c net -n $iface ; /usr/sbin/ifconfig $iface 2>/dev/null"
else
CMD_DESCRIBE_INTERFACE="eval kstat -n $iface ; /usr/sbin/ifconfig $iface 2>/dev/null"
fi
$CMD_DESCRIBE_INTERFACE | tee -a "$TEE_DEST" | $AWK "$GET_ALL $FORMAT $PRINTF" name="$iface" node="$NODE"
echo "Cmd = [$CMD_DESCRIBE_INTERFACE]; | $AWK '$GET_ALL $FORMAT $PRINTF' name=$iface node=$NODE" >> "$TEE_DEST"
done
elif [ "$KERNEL" = "AIX" ] ; then
assertHaveCommandGivenPath /usr/sbin/ifconfig
assertHaveCommandGivenPath /usr/bin/netstat
# shellcheck disable=SC2089
CMD_LIST_INTERFACES="eval /usr/sbin/ifconfig -au | tee $TEE_DEST | egrep -v 'LOOPBACK|netmask|inet6|tcp_sendspace' | tee -a $TEE_DEST | grep flags | cut -d':' -f1 | tee -a $TEE_DEST | sort -u | tee -a $TEE_DEST"
# shellcheck disable=SC2016
GET_COLLISIONS_RXbytes_TXbytes_SPEED_DUPLEX_ERRORS='($1=="Single"){collisions_s=$4} ($1=="Multiple"){collisions=collisions_s+$4} ($1=="Bytes:") {RXbytes=$4 ; TXbytes=$2} ($1=="Media" && $3=="Running:") {speed=$4"Mb/s" ; duplex=$6} ($1="Transmit" && $2="Errors:") {TXerrors=$3 ; RXerrors=$6}'
# shellcheck disable=SC2016
GET_IP='/ netmask / {for (i=1; i<=NF; i++) {if ($i == "inet") IPv4 = $(i+1); if ($i == "inet6") IPv6 = $(i+1)}}'
# shellcheck disable=SC2016
GET_MAC='/^Hardware Address:/{mac=$3}'
FILL_BLANKS='{length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>"; IPv4 = IPv4 ? IPv4 : "<n/a>"; IPv6 = IPv6 ? IPv6 : "<n/a>"}'
GET_ALL="$GET_COLLISIONS_RXbytes_TXbytes_SPEED_DUPLEX_ERRORS $GET_IP $GET_MAC $FILL_BLANKS"
# shellcheck disable=SC2090
out=$($CMD_LIST_INTERFACES)
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
fi
for iface in $out
do
echo "Cmd = [$CMD_LIST_INTERFACES]" >> "$TEE_DEST"
NODE=$(uname -n)
CMD_DESCRIBE_INTERFACE="eval netstat -v $iface ; /usr/sbin/ifconfig $iface"
$CMD_DESCRIBE_INTERFACE | tee -a "$TEE_DEST" | $AWK "$GET_ALL $FORMAT $PRINTF" name="$iface" node="$NODE"
echo "Cmd = [$CMD_DESCRIBE_INTERFACE]; | $AWK '$GET_ALL $FORMAT $PRINTF' name=$iface node=$NODE" >> "$TEE_DEST"
done
elif [ "$KERNEL" = "Darwin" ] ; then
assertHaveCommand ifconfig
assertHaveCommand netstat
CMD_LIST_INTERFACES='ifconfig -u'
# shellcheck disable=SC2016
CHOOSE_ACTIVE='/^[a-z0-9]+: / {sub(":", "", $1); iface=$1} /status: active/ {print iface}'
# shellcheck disable=SC2016
UNIQUE='sort -u'
# shellcheck disable=SC2016
GET_MAC='{$1 == "ether" && mac = $2}'
# shellcheck disable=SC2016
GET_IPv4='{$1 == "inet" && IPv4 = $2}'
# shellcheck disable=SC2016
GET_IPv6='{if ($1 == "inet6") {sub("%.*$", "", $2);IPv6 = $2}}'
# shellcheck disable=SC2016
GET_SPEED_DUPLEX='{if ($1 == "media:") {gsub("[^0-9]", "", $3); speed=$3 "Mb/s"; sub("-duplex.*", "", $4); sub("<", "", $4); duplex=$4}}'
# shellcheck disable=SC2016
GET_RXbytes_TXbytes_COLLISIONS_ERRORS='{
if ($0 ~ /Name/)
{
for (i=1; i<=NF; i++)
{
if ($i == "Address") {address_column = i;}
else if ($i == "Ibytes") {ibytes_column = i;}
else if ($i == "Ierrs") {ierrs_column = i;}
else if ($i == "Obytes") {obytes_column = i;}
else if ($i == "Oerrs") {oerrs_column = i;}
else if ($i == "Coll") {coll_column = i;}
}
flag = 1;
}
if(flag == 1){
if ($address_column == mac)
{
(ibytes_column == "") ? RXbytes = "<n/a>" : RXbytes = $(ibytes_column);
(ierrs_column == "") ? RXerrors = "<n/a>" : RXerrors = $(ierrs_column);
(obytes_column == "") ? TXbytes = "<n/a>" : TXbytes = $(obytes_column);
(oerrs_column == "") ? TXerrors = "<n/a>" : TXerrors = $(oerrs_column);
(coll_column == "") ? collisions = "<n/a>" : collisions = $(coll_column);
}
}
}'
FILL_BLANKS='{length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>"; IPv4 = IPv4 ? IPv4 : "<n/a>"; IPv6 = IPv6 ? IPv6 : "<n/a>"}'
GET_ALL="$GET_MAC $GET_IPv4 $GET_IPv6 $GET_SPEED_DUPLEX $GET_RXbytes_TXbytes_COLLISIONS_ERRORS $FILL_BLANKS"
out=$($CMD_LIST_INTERFACES | tee "$TEE_DEST" | awk "$CHOOSE_ACTIVE" | $UNIQUE | tee -a "$TEE_DEST")
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
fi
for iface in $out
do
echo "Cmd = [$CMD_LIST_INTERFACES]; | awk '$CHOOSE_ACTIVE' | $UNIQUE" >> "$TEE_DEST"
CMD_DESCRIBE_INTERFACE="eval ifconfig $iface ; netstat -b -I $iface"
$CMD_DESCRIBE_INTERFACE | tee -a "$TEE_DEST" | awk "$GET_ALL $PRINTF" name="$iface"
echo "Cmd = [$CMD_DESCRIBE_INTERFACE]; | awk '$GET_ALL $PRINTF' name=$iface" >> "$TEE_DEST"
done
elif [ "$KERNEL" = "HP-UX" ] ; then
assertHaveCommand ifconfig
assertHaveCommand lanadmin
assertHaveCommand lanscan
assertHaveCommand netstat
CMD='lanscan'
# shellcheck disable=SC2016
LANSCAN_AWK='/^Hardware/ {next} /^Path/ {next} {mac=$2; ifnum=$3; ifstate=$4; name=$5; type=$8}'
# shellcheck disable=SC2016
GET_IP4='{c="netstat -niwf inet | grep "name; c | getline; close(c); if (NF==10) {next} mtu=$2; IPv4=$4; RXbytes=$5; RXerrors=$6; TXbytes=$7; TXerrors=$8; collisions=$9}'
# shellcheck disable=SC2016
GET_IP6='{c="netstat -niwf inet6 | grep "name" "; c| getline; close(c); IPv6=$3}'
# shellcheck disable=SC2016
GET_SPEED_DUPLEX='{c="lanadmin -x "ifnum ; c | getline; close(c); if (NF==4) speed=$3"Mb/s"; sub("\-.*", "", $4); duplex=tolower($4)}'
PRINTF='{printf "%-10s %-17s %-15s %-42s %-10s %-16s %-16s %-16s %-16s %-12s %-12s\n", name, mac, IPv4, IPv6, collisions, RXbytes, RXerrors, TXbytes, TXerrors, speed, duplex}'
FILL_BLANKS='{length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>"; IPv4 = IPv4 ? IPv4 : "<n/a>"; IPv6 = IPv6 ? IPv6 : "<n/a>"}'
out=$($CMD | awk "$LANSCAN_AWK $GET_IP4 $GET_IP6 $GET_SPEED_DUPLEX $PRINTF $FILL_BLANKS")
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
echo "$out"
fi
elif [ "$KERNEL" = "FreeBSD" ] ; then
assertHaveCommand ifconfig
assertHaveCommand netstat
CMD_LIST_INTERFACES='ifconfig -a'
# shellcheck disable=SC2016
CHOOSE_ACTIVE='/LOOPBACK/ {next} !/RUNNING/ {next} /^[a-z0-9]+: / {sub(":$", "", $1); print $1}'
UNIQUE='sort -u'
# shellcheck disable=SC2016
GET_MAC='{$1 == "ether" && mac = $2}'
# shellcheck disable=SC2016
GET_IP='/ netmask / {for (i=1; i<=NF; i++) {if ($i == "inet") IPv4 = $(i+1); if ($i == "inet6") IPv6 = $(i+1)}}'
# shellcheck disable=SC2016
GET_SPEED_DUPLEX='/media: / {sub("\134(", "", $4); speed=$4; sub("-duplex.*", "", $5); sub("<", "", $5); duplex=$5}'
# shellcheck disable=SC2016
GET_RXbytes_TXbytes_COLLISIONS_ERRORS='{
if ($0 ~ /Name/)
{
for (i=1; i<=NF; i++)
{
if ($i == "Address") {address_column = i;}
else if ($i == "Ibytes") {ibytes_column = i;}
else if ($i == "Ierrs") {ierrs_column = i;}
else if ($i == "Obytes") {obytes_column = i;}
else if ($i == "Oerrs") {oerrs_column = i;}
else if ($i == "Coll") {coll_column = i;}
}
flag = 1;
}
if(flag == 1){
if ($address_column == mac)
{
(ibytes_column == "") ? RXbytes = "<n/a>" : RXbytes = $(ibytes_column);
(ierrs_column == "") ? RXerrors = "<n/a>" : RXerrors = $(ierrs_column);
(obytes_column == "") ? TXbytes = "<n/a>" : TXbytes = $(obytes_column);
(oerrs_column == "") ? TXerrors = "<n/a>" : TXerrors = $(oerrs_column);
(coll_column == "") ? collisions = "<n/a>" : collisions = $(coll_column);
}
}
}'
FILL_BLANKS='{length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>"; IPv4 = IPv4 ? IPv4 : "<n/a>"; IPv6 = IPv6 ? IPv6 : "<n/a>"}'
GET_ALL="$GET_MAC $GET_IP $GET_SPEED_DUPLEX $GET_RXbytes_TXbytes_COLLISIONS_ERRORS $FILL_BLANKS"
out=$($CMD_LIST_INTERFACES | tee "$TEE_DEST" | awk "$CHOOSE_ACTIVE" | $UNIQUE | tee -a "$TEE_DEST")
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
fi
for iface in $out
do
echo "Cmd = [$CMD_LIST_INTERFACES]; | awk '$CHOOSE_ACTIVE' | $UNIQUE" >> "$TEE_DEST"
CMD_DESCRIBE_INTERFACE="eval ifconfig $iface ; netstat -b -I $iface"
$CMD_DESCRIBE_INTERFACE | tee -a "$TEE_DEST" | awk "$GET_ALL $PRINTF" name="$iface"
echo "Cmd = [$CMD_DESCRIBE_INTERFACE]; | awk '$GET_ALL $PRINTF' name=$iface" >> "$TEE_DEST"
done
fi
# jscpd:ignore-end

547
bin/interfaces_metric.sh Executable file
View file

@ -0,0 +1,547 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# jscpd:ignore-start
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER='Name MAC inetAddr inet6Addr Collisions RXbytes RXerrors TXbytes TXerrors Speed Duplex OSName OS_version IP_address IPv6_Address'
FORMAT='{mac = length(mac) ? mac : "?"; collisions = length(collisions) ? collisions : "?"; RXbytes = length(RXbytes) ? RXbytes : "?"; RXerrors = length(RXerrors) ? RXerrors : "?"; TXbytes = length(TXbytes) ? TXbytes : "?"; TXerrors = length(TXerrors) ? TXerrors : "?"; speed = length(speed) ? speed : "?"; duplex = length(duplex) ? duplex : "?"}'
PRINTF='END {printf "%-10s %-17s %-15s %-42s %-10s %-16s %-16s %-16s %-16s %-12s %-12s %-35s %15s %-16s %-42s\n", name, mac, IPv4, IPv6, collisions, RXbytes, RXerrors, TXbytes, TXerrors, speed, duplex, OSName, OS_version, IP_address, IPv6_Address}'
if [ "$KERNEL" = "Linux" ] ; then
OS_FILE=/etc/os-release
HEADER='Name MAC inetAddr inet6Addr Collisions RXbytes RXerrors RXdropped TXbytes TXerrors TXdropped Speed Duplex OSName OS_version IP_address IPv6_Address'
PRINTF='END {printf "%-10s %-17s %-15s %-42s %-10s %-16s %-16s %-18s %-16s %-16s %-18s %-12s %-12s %-35s %15s %-16s %-42s\n", name, mac, IPv4, IPv6, collisions, RXbytes, RXerrors, RXdropped, TXbytes, TXerrors, TXdropped, speed, duplex, OSName, OS_version, IP_address, IPv6_Address}'
queryHaveCommand ip
FOUND_IP=$?
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=$(hostname -I | cut -d\ -f1) -v IPv6_Address=$(ip -6 -brief address show scope global | xargs | cut -d ' ' -f 3 | cut -d '/' -f 1)"
else
DEFINE="-v OSName=$(cat /etc/*release | grep '\bNAME=' | cut -d '=' -f2 | tr ' ' '_' | cut -d\" -f2) -v OS_version=$(cat /etc/*release | grep '\bVERSION_ID=' | cut -d '=' -f2 | cut -d\" -f2) -v IP_address=$(hostname -I | cut -d\ -f1) -v IPv6_Address=$(ip -6 -brief address show scope global | xargs | cut -d ' ' -f 3 | cut -d '/' -f 1)"
fi
if [ $FOUND_IP -eq 0 ]; then
CMD_LIST_INTERFACES="eval ip -s a | tee $TEE_DEST|grep 'state UP' | grep mtu | grep -Ev lo | tee -a $TEE_DEST | cut -d':' -f2 | tee -a $TEE_DEST | cut -d '@' -f 1 | tee -a $TEE_DEST | sort -u | tee -a $TEE_DEST"
# shellcheck disable=SC2016
CMD='eval ip addr show $iface; ip -s link show'
# shellcheck disable=SC2016
GET_IPv4='{if ($0 ~ /inet /) {split($2, a, " "); IPv4 = a[1]}}'
# shellcheck disable=SC2016
GET_IPv6='{if ($0 ~ /inet6 /) { IPv6 = $2 }}'
# shellcheck disable=SC2016
GET_TXbytes='{
if($0 ~ /TX: /){
tx_row_count=NR+1;
for(i=1;i<=NF;i++){
if($i=="bytes"){
TX_bytes_column=i;
}
else if($i=="errors"){
TX_errors_column=i;
}
else if($i=="dropped"){
TX_dropped_column=i;
}
else if($i=="collsns"){
TX_collsns_column=i;
}
}
next;
}
if(NR==tx_row_count){
(TX_bytes_column == "") ? TXbytes = 0 : TXbytes = $(TX_bytes_column - 1);
(TX_errors_column == "") ? TXerrors = "<n/a>" : TXerrors = $(TX_errors_column - 1);
(TX_dropped_column == "") ? TXdropped = "<n/a>" : TXdropped = $(TX_dropped_column - 1);
(TX_collsns_column == "") ? collisions = 0 : collisions = $(TX_collsns_column - 1);
}
}'
# shellcheck disable=SC2016
GET_RXbytes='{
if($0 ~ /RX: /){
rx_row_count=NR+1;
for(i=1;i<=NF;i++){
if($i=="bytes"){
RX_bytes_column=i;
}
else if($i=="errors"){
RX_errors_column=i;
}
else if($i=="dropped"){
RX_dropped_column=i;
}
}next;
}
if(NR==rx_row_count){
(RX_bytes_column == "") ? RXbytes = 0 : RXbytes = $(RX_bytes_column - 1);
(RX_errors_column == "") ? RXerrors = "<n/a>" : RXerrors = $(RX_errors_column - 1);
(RX_dropped_column == "") ? RXdropped = "<n/a>" : RXdropped = $(RX_dropped_column - 1);
}
}'
else
assertHaveCommand ifconfig
# shellcheck disable=SC2089
CMD_LIST_INTERFACES="eval ifconfig | tee $TEE_DEST | grep 'Link encap:\|mtu' | grep -Ev lo | tee -a $TEE_DEST | cut -d' ' -f1 | cut -d':' -f1 | tee -a $TEE_DEST | sort -u | tee -a $TEE_DEST"
CMD='ifconfig'
# shellcheck disable=SC2016
GET_IPv4='{if ($0 ~ /inet addr:/) {split($2, a, ":"); IPv4 = a[2]} else if ($0 ~ /inet /) {IPv4 = $2}}'
# shellcheck disable=SC2016
GET_IPv6='{if ($0 ~ /inet6 addr:/) { IPv6 = $3 } else if ($0 ~ /inet6 /) { IPv6 = $2 }}'
# shellcheck disable=SC2016
GET_COLLISIONS='{
if ($0 ~ /collisions:/){
for(i=1;i<=NF;i++){
if($i ~ /collisions:/){
collisions_col_no = i;
break;
}
}
if(collisions_col_no==""){
collisions=0;
}
else
split($collisions_col_no, a, ":");
collisions=a[2];
}
else if($0 ~ /collisions /){
for(i=1;i<=NF;i++){
if($i=="collisions"){
collisions_column=i+1;
}
}
(collisions_column != "") ? collisions = $collisions_column : collisions = 0;
}
}'
# shellcheck disable=SC2016
GET_RXbytes='{
if ($0 ~ /RX bytes:/){
for(i=1;i<=NF;i++){
if($i ~ /bytes:/){
rxbytes_col_no = i;
break;
}
}
if(rxbytes_col_no==""){
RXbytes=0;
}
else
split($rxbytes_col_no, a, ":");
RXbytes=a[2];
}
else if($0 ~ /RX/ && $0 ~ /bytes/){
for(i=1;i<=NF;i++){
if($i=="bytes"){
RXbytes_column=i+1;
row = NR;
}
}
if(NR == row){
if(RXbytes_column != ""){
RXbytes = $RXbytes_column;
}
else
RXbytes = 0;
}
}
}'
# shellcheck disable=SC2016
GET_RXerrors='{
if ($0 ~ /RX packets:/){
for(i=1;i<=NF;i++){
if($i ~ /errors:/){
rxerrors_col_no = i;
}
else if($i ~ /dropped:/){
rxdropped_col_no = i;
}
}
if(rxerrors_col_no != ""){
split($rxerrors_col_no, a, ":");
RXerrors=a[2];
}
else
RXerrors="<n/a>";
if(rxdropped_col_no != ""){
split($rxdropped_col_no, b, ":");
RXdropped=b[2];
}
else
RXdropped="<n/a>";
}
else if($0 ~ /RX/ && ($0 ~ /errors/)){
for(i=1;i<=NF;i++){
if($i=="errors"){
RXerrors_column=i+1;
}
if($i=="dropped"){
RXdropped_column=i+1;
}
}
(RXerrors_column != "") ? RXerrors=$RXerrors_column : RXerrors = "<n/a>";
(RXdropped_column != "") ? RXdropped = $RXdropped_column : RXdropped = "<n/a>";
}
}'
# shellcheck disable=SC2016
GET_TXbytes='{
if ($0 ~ /TX bytes:/){
for(i=1;i<=NF;i++){
if($i ~ /bytes:/){
txbytes_col_no = i;
}
}
if(txbytes_col_no==""){
TXbytes=0;
}
else
split($txbytes_col_no, a, ":");
TXbytes=a[2];
}
else if($0 ~ /TX/ && $0 ~ /bytes/){
for(i=1;i<=NF;i++){
if($i=="bytes"){
TXbytes_column=i+1;
row = NR;
}
}
if(NR == row){
if(TXbytes_column != ""){
TXbytes = $TXbytes_column;
}
else
TXbytes = 0;
}
}
}'
# shellcheck disable=SC2016
GET_TXerrors='{
if ($0 ~ /TX packets:/){
for(i=1;i<=NF;i++){
if($i ~ /errors:/){
txerrors_col_no = i;
}
if($i ~ /dropped:/){
txdropped_col_no = i;
}
}
if(txerrors_col_no != ""){
split($txerrors_col_no, a, ":");
TXerrors=a[2];
}
else
TXerrors="<n/a>";
if(txdropped_col_no != ""){
split($txdropped_col_no, b, ":");
TXdropped=b[2];
}
else
TXdropped="<n/a>";
}
else if($0 ~ /TX/ && $0 ~ /errors/){
for(i=1;i<=NF;i++){
if($i=="errors"){
TXerrors_column=i+1;
}
if($i=="dropped"){
TXdropped_column=i+1;
}
}
(TXerrors_column != "") ? TXerrors = $TXerrors_column : TXerrors = "<n/a>";
(TXdropped_column != "") ? TXdropped = $TXdropped_column : TXdropped = "<n/a>";
}
}'
fi
GET_ALL="$GET_IPv4 $GET_IPv6 $GET_COLLISIONS $GET_RXbytes $GET_RXerrors $GET_TXbytes $GET_TXerrors"
FILL_BLANKS='{length(TXdropped) || TXdropped = "<n/a>";length(RXdropped) || RXdropped = "<n/a>";length(IP_address) || IP_address = "?";length(OS_version) || OS_version = "?";length(OSName) || OSName = "?"; length(IPv6_Address) || IPv6_Address = "?"; length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>"; length(IPv4) || IPv4 = "<n/a>"; length(IPv6) || IPv6= "<n/a>"}'
BEGIN='BEGIN {RXbytes = RXerrors = RXdropped = TXbytes = TXerrors = TXdropped = collisions = 0}'
# shellcheck disable=SC2090
out=$($CMD_LIST_INTERFACES)
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
fi
for iface in $out
do
if [ -r /sys/class/net/"$iface"/duplex ]; then
DUPLEX=$(cat /sys/class/net/"$iface"/duplex 2>/dev/null || echo 'error')
if [ "$DUPLEX" != 'error' ]; then
DUPLEX=$(echo "$DUPLEX" | sed 's/./\u&/')
if [ -r /sys/class/net/"$iface"/speed ]; then
SPEED=$(cat /sys/class/net/"$iface"/speed 2>/dev/null || echo 'error')
[ -n "$SPEED" ] && [ "$SPEED" != 'error' ] && SPEED="${SPEED}Mb/s"
else
# For SLES, dmesg is accesbile only by the root user, thus using ethtool
if echo "$OS_ID" | grep -qi suse; then
assertHaveCommandGivenPath /usr/sbin/ethtool
SPEED=$(/usr/sbin/ethtool $iface 2>/dev/null | awk '/Speed: +[0-9]+Mb\/s/ {print gensub(/[[:space:]]*Speed: +/, "", 1)}')
# For Ubuntu version >= 20, we use cat to read the dmseg file. Otherwise we use dmesg cmd.
elif [ -e "$DMESG_FILE" ] && [ "$UBUNTU_MAJOR_VERSION" -ge 20 ] ; then
SPEED=$(cat "$DMESG_FILE"* | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([0-9]+)([Mm]bps)/)) {print $i} else { if (match($i, /[Mm]bps/)) {print $(i-1) "Mb/s"} } } }' | sed '$!d')
else
assertHaveCommand dmesg
SPEED=$(dmesg | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([0-9]+)([Mm]bps)/)) {print $i} else { if (match($i, /[Mm]bps/)) {print $(i-1) "Mb/s"} } } }' | sed '$!d')
fi
fi
else
DUPLEX=""
fi
fi
if [ "$DUPLEX" = "" ] || [ "$SPEED" = "" ] ; then
# Get Duplex only if still null
if [ "$DUPLEX" = "" ] ; then
if echo "$OS_ID" | grep -qi suse; then
assertHaveCommandGivenPath /usr/sbin/ethtool
DUPLEX=$(/usr/sbin/ethtool $iface 2>/dev/null | awk '/Duplex: +[A-Za-z]+/ {print gensub(/[[:space:]]*Duplex: +/, "", 1)}')
elif [ -e "$DMESG_FILE" ] && [ "$UBUNTU_MAJOR_VERSION" -ge 20 ] ; then
DUPLEX=$(cat "$DMESG_FILE"* | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([-_a-zA-Z0-9]+)([Dd]uplex)/)) {print $i} else { if (match($i, /[Dd]uplex/)) {print $(i-1) } } } }' | sed 's/[-_]//g; $!d')
else
assertHaveCommand dmesg
DUPLEX=$(dmesg | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([-_a-zA-Z0-9]+)([Dd]uplex)/)) {print $i} else { if (match($i, /[Dd]uplex/)) {print $(i-1) } } } }' | sed 's/[-_]//g; $!d')
fi
fi
# Get Speed only if still null
if [ "$SPEED" = "" ] ; then
if echo "$OS_ID" | grep -qi suse; then
assertHaveCommandGivenPath /usr/sbin/ethtool
SPEED=$(/usr/sbin/ethtool $iface 2>/dev/null | awk '/Speed: +[0-9]+Mb\/s/ {print gensub(/[[:space:]]*Speed: +/, "", 1)}')
elif [ -e "$DMESG_FILE" ] && [ "$UBUNTU_MAJOR_VERSION" -ge 20 ] ; then
SPEED=$(cat "$DMESG_FILE"* | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([0-9]+)([Mm]bps)/)) {print $i} else { if (match($i, /[Mm]bps/)) {print $(i-1) "Mb/s"} } } }' | sed '$!d')
else
assertHaveCommand dmesg
SPEED=$(dmesg | awk '/[Ll]ink( is | )[Uu]p/ && /'"$iface"'/ {for (i=1; i<=NF; ++i) {if (match($i, /([0-9]+)([Mm]bps)/)) {print $i} else { if (match($i, /[Mm]bps/)) {print $(i-1) "Mb/s"} } } }' | sed '$!d')
fi
fi
fi
if [ $FOUND_IP -eq 0 ]; then
# shellcheck disable=SC2016
GET_MAC='{if ($0 ~ /ether /) { mac = $2 }}'
elif [ -r /sys/class/net/"$iface"/address ]; then
MAC=$(cat /sys/class/net/"$iface"/address)
else
# shellcheck disable=SC2016
GET_MAC='{if ($0 ~ /ether /) { mac = $2; } else if ( NR == 1 ) { mac = $5; }}'
fi
if [ "$DUPLEX" != 'error' ] && [ "$SPEED" != 'error' ]; then
# shellcheck disable=SC2086
$CMD "$iface" | tee -a "$TEE_DEST" | awk $DEFINE "$BEGIN $GET_MAC $GET_ALL $FILL_BLANKS $PRINTF" name="$iface" speed="$SPEED" duplex="$DUPLEX" mac="$MAC"
echo "Cmd = [$CMD $iface]; | awk $DEFINE '$BEGIN $GET_MAC $GET_ALL $FILL_BLANKS $PRINTF' name=$iface speed=$SPEED duplex=$DUPLEX mac=$MAC" >> "$TEE_DEST"
else
echo "ERROR: cat command failed for interface $iface" >> "$TEE_DEST"
fi
done
elif [ "$KERNEL" = "SunOS" ] ; then
assertHaveCommandGivenPath /usr/sbin/ifconfig
assertHaveCommand kstat
# shellcheck disable=SC2089
CMD_LIST_INTERFACES="eval /usr/sbin/ifconfig -au | tee $TEE_DEST | egrep -v 'LOOPBACK|netmask' | tee -a $TEE_DEST | grep flags | cut -d':' -f1 | tee -a $TEE_DEST | sort -u | tee -a $TEE_DEST"
# Filters have been applied to get rid of IPv6 addresses designated for special usage to extract only the global IPv6 address.
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) -v IPv6_Address=$(ifconfig -a | grep inet6 | grep -v ' ::1 ' | grep -v ' ::1/' | grep -v ' ::1%' | grep -v ' fe80::' | grep -v ' 2002::' | grep -v ' ff00::' | head -n 1 | xargs | cut -d '/' -f 1 | cut -d '%' -f 1 | cut -d ' ' -f 2)"
# shellcheck disable=SC2016
GET_COLLISIONS_RXbytes_TXbytes_SPEED_DUPLEX='($1=="collisions") {collisions=$2} ($1=="duplex" || $1=="link_duplex") {duplex=$2} ($1=="rbytes") {RXbytes=$2} ($1=="obytes") {TXbytes=$2} ($1=="ierrors") {RXerrors=$2} ($1=="oerrors") {TXerrors=$2} ($1=="ifspeed") {speed=$2; speed/=1000000; speed=speed "Mb/s"}'
# shellcheck disable=SC2016
GET_IP='/ netmask / {for (i=1; i<=NF; i++) {if ($i == "inet") IPv4 = $(i+1); if ($i == "inet6") IPv6 = $(i+1)}}'
# shellcheck disable=SC2016
GET_MAC='{if ($1 == "ether") {split($2, submac, ":"); mac=sprintf("%02s:%02s:%02s:%02s:%02s:%02s", submac[1], submac[2], submac[3], submac[4], submac[5], submac[6])}}'
FILL_BLANKS='{length(IP_address) || IP_address = "?";length(OS_version) || OS_version = "?";length(OSName) || OSName = "?"; length(IPv6_Address) || IPv6_Address = "?"; length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>";IPv4 = IPv4 ? IPv4 : "<n/a>"; IPv6 = IPv6 ? IPv6 : "<n/a>"}'
GET_ALL="$GET_COLLISIONS_RXbytes_TXbytes_SPEED_DUPLEX $GET_IP $GET_MAC $FILL_BLANKS"
# shellcheck disable=SC2090
out=$($CMD_LIST_INTERFACES)
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
fi
for iface in $out
do
echo "Cmd = [$CMD_LIST_INTERFACES]" >> "$TEE_DEST"
NODE=$(uname -n)
# shellcheck disable=SC2050
if [ SOLARIS_8 = false ] && [ SOLARIS_9 = false ] ; then
CMD_DESCRIBE_INTERFACE="eval kstat -c net -n $iface ; /usr/sbin/ifconfig $iface 2>/dev/null"
else
CMD_DESCRIBE_INTERFACE="eval kstat -n $iface ; /usr/sbin/ifconfig $iface 2>/dev/null"
fi
# shellcheck disable=SC2086
$CMD_DESCRIBE_INTERFACE | tee -a "$TEE_DEST" | $AWK $DEFINE "$GET_ALL $FORMAT $PRINTF" name="$iface" node="$NODE"
echo "Cmd = [$CMD_DESCRIBE_INTERFACE]; | $AWK $DEFINE '$GET_ALL $FORMAT $PRINTF' name=$iface node=$NODE" >> "$TEE_DEST"
done
elif [ "$KERNEL" = "AIX" ] ; then
assertHaveCommandGivenPath /usr/sbin/ifconfig
assertHaveCommandGivenPath /usr/bin/netstat
# shellcheck disable=SC2089
CMD_LIST_INTERFACES="eval /usr/sbin/ifconfig -au | tee $TEE_DEST | egrep -v 'LOOPBACK|netmask|inet6|tcp_sendspace' | tee -a $TEE_DEST | grep flags | cut -d':' -f1 | tee -a $TEE_DEST | sort -u | tee -a $TEE_DEST"
# Filters have been applied to get rid of IPv6 addresses designated for special usage to extract only the global IPv6 address.
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) -v IPv6_Address=$(ifconfig -a | grep inet6 | grep -v ' ::1 ' | grep -v ' ::1/' | grep -v ' ::1%' | grep -v ' fe80::' | grep -v ' 2002::' | grep -v ' ff00::' | head -n 1 | xargs | cut -d '/' -f 1 | cut -d '%' -f 1 | cut -d ' ' -f 2)"
# shellcheck disable=SC2016
GET_COLLISIONS_RXbytes_TXbytes_SPEED_DUPLEX_ERRORS='($1=="Single"){collisions_s=$4} ($1=="Multiple"){collisions=collisions_s+$4} ($1=="Bytes:") {RXbytes=$4 ; TXbytes=$2} ($1=="Media" && $3=="Running:") {speed=$4"Mb/s" ; duplex=$6} ($1="Transmit" && $2="Errors:") {TXerrors=$3 ; RXerrors=$6}'
# shellcheck disable=SC2016
GET_IP='/ netmask / {for (i=1; i<=NF; i++) {if ($i == "inet") IPv4 = $(i+1); if ($i == "inet6") IPv6 = $(i+1)}}'
# shellcheck disable=SC2016
GET_MAC='/^Hardware Address:/{mac=$3}'
GET_OS_VERSION='{OS_version=OSVersion/1000}'
FILL_BLANKS='{length(IP_address) || IP_address = "?";length(OS_version) || OS_version = "?";length(OSName) || OSName = "?"; length(IPv6_Address) || IPv6_Address = "?"; length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>"; IPv4 = IPv4 ? IPv4 : "<n/a>"; IPv6 = IPv6 ? IPv6 : "<n/a>"}'
GET_ALL="$GET_COLLISIONS_RXbytes_TXbytes_SPEED_DUPLEX_ERRORS $GET_IP $GET_MAC $GET_OS_VERSION $FILL_BLANKS"
# shellcheck disable=SC2090
out=$($CMD_LIST_INTERFACES)
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
fi
for iface in $out
do
echo "Cmd = [$CMD_LIST_INTERFACES]" >> "$TEE_DEST"
NODE=$(uname -n)
CMD_DESCRIBE_INTERFACE="eval netstat -v $iface ; /usr/sbin/ifconfig $iface"
# shellcheck disable=SC2086
$CMD_DESCRIBE_INTERFACE | tee -a "$TEE_DEST" | $AWK $DEFINE "$GET_ALL $FORMAT $PRINTF" name="$iface" node="$NODE"
echo "Cmd = [$CMD_DESCRIBE_INTERFACE]; | $AWK $DEFINE '$GET_ALL $FORMAT $PRINTF' name=$iface node=$NODE" >> "$TEE_DEST"
done
elif [ "$KERNEL" = "Darwin" ] ; then
assertHaveCommand ifconfig
assertHaveCommand netstat
CMD_LIST_INTERFACES='ifconfig -u'
# Filters have been applied to get rid of IPv6 addresses designated for special usage to extract only the global IPv6 address.
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) -v IPv6_Address=$(ifconfig -a | grep inet6 | grep -v ' ::1 ' | grep -v ' ::1/' | grep -v ' ::1%' | grep -v ' fe80::' | grep -v ' 2002::' | grep -v ' ff00::' | head -n 1 | xargs | cut -d '/' -f 1 | cut -d '%' -f 1 | cut -d ' ' -f 2)"
# shellcheck disable=SC2016
CHOOSE_ACTIVE='/^[a-z0-9]+: / {sub(":", "", $1); iface=$1} /status: active/ {print iface}'
UNIQUE='sort -u'
# shellcheck disable=SC2016
GET_MAC='{$1 == "ether" && mac = $2}'
# shellcheck disable=SC2016
GET_IPv4='{$1 == "inet" && IPv4 = $2}'
# shellcheck disable=SC2016
GET_IPv6='{if ($1 == "inet6") {sub("%.*$", "", $2);IPv6 = $2}}'
# shellcheck disable=SC2016
GET_SPEED_DUPLEX='{if ($1 == "media:") {gsub("[^0-9]", "", $3); speed=$3 "Mb/s"; sub("-duplex.*", "", $4); sub("<", "", $4); duplex=$4}}'
# shellcheck disable=SC2016
GET_RXbytes_TXbytes_COLLISIONS_ERRORS='{
if ($0 ~ /Name/)
{
for (i=1; i<=NF; i++)
{
if ($i == "Address") {address_column = i;}
else if ($i == "Ibytes") {ibytes_column = i;}
else if ($i == "Ierrs") {ierrs_column = i;}
else if ($i == "Obytes") {obytes_column = i;}
else if ($i == "Oerrs") {oerrs_column = i;}
else if ($i == "Coll") {coll_column = i;}
}
flag = 1;
}
if(flag == 1){
if ($address_column == mac)
{
(ibytes_column == "") ? RXbytes = "<n/a>" : RXbytes = $(ibytes_column);
(ierrs_column == "") ? RXerrors = "<n/a>" : RXerrors = $(ierrs_column);
(obytes_column == "") ? TXbytes = "<n/a>" : TXbytes = $(obytes_column);
(oerrs_column == "") ? TXerrors = "<n/a>" : TXerrors = $(oerrs_column);
(coll_column == "") ? collisions = "<n/a>" : collisions = $(coll_column);
}
}
}'
FILL_BLANKS='{length(IP_address) || IP_address = "?";length(OS_version) || OS_version = "?";length(OSName) || OSName = "?"; length(IPv6_Address) || IPv6_Address = "?"; length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>"; IPv4 = IPv4 ? IPv4 : "<n/a>"; IPv6 = IPv6 ? IPv6 : "<n/a>"}'
GET_ALL="$GET_MAC $GET_IPv4 $GET_IPv6 $GET_SPEED_DUPLEX $GET_RXbytes_TXbytes_COLLISIONS_ERRORS $FILL_BLANKS"
out=$($CMD_LIST_INTERFACES | tee "$TEE_DEST" | awk "$CHOOSE_ACTIVE" | $UNIQUE | tee -a "$TEE_DEST")
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
fi
for iface in $out
do
echo "Cmd = [$CMD_LIST_INTERFACES]; | awk '$CHOOSE_ACTIVE' | $UNIQUE" >> "$TEE_DEST"
CMD_DESCRIBE_INTERFACE="eval ifconfig $iface ; netstat -b -I $iface"
# shellcheck disable=SC2086
$CMD_DESCRIBE_INTERFACE | tee -a "$TEE_DEST" | awk $DEFINE "$GET_ALL $PRINTF" name="$iface"
echo "Cmd = [$CMD_DESCRIBE_INTERFACE]; | awk $DEFINE '$GET_ALL $PRINTF' name=$iface" >> "$TEE_DEST"
done
elif [ "$KERNEL" = "HP-UX" ] ; then
assertHaveCommand ifconfig
assertHaveCommand lanadmin
assertHaveCommand lanscan
assertHaveCommand netstat
CMD='lanscan'
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
LANSCAN_AWK='/^Hardware/ {next} /^Path/ {next} {mac=$2; ifnum=$3; ifstate=$4; name=$5; type=$8}'
# shellcheck disable=SC2016
GET_IP4='{c="netstat -niwf inet | grep "name; c | getline; close(c); if (NF==10) {next} mtu=$2; IPv4=$4; RXbytes=$5; RXerrors=$6; TXbytes=$7; TXerrors=$8; collisions=$9}'
# shellcheck disable=SC2016
GET_IP6='{c="netstat -niwf inet6 | grep "name" "; c| getline; close(c); IPv6=$3}'
# shellcheck disable=SC2016
GET_SPEED_DUPLEX='{c="lanadmin -x "ifnum ; c | getline; close(c); if (NF==4) speed=$3"Mb/s"; sub("\-.*", "", $4); duplex=tolower($4)}'
PRINTF='{printf "%-10s %-17s %-15s %-42s %-10s %-16s %-16s %-16s %-16s %-12s %-12s %-35s %15s %-16s\n", name, mac, IPv4, IPv6, collisions, RXbytes, RXerrors, TXbytes, TXerrors, speed, duplex, OSName, OS_version, IP_address}'
FILL_BLANKS='{length(IP_address) || IP_address = "?";length(OS_version) || OS_version = "?";length(OSName) || OSName = "?";length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>"; IPv4 = IPv4 ? IPv4 : "<n/a>"; IPv6 = IPv6 ? IPv6 : "<n/a>"}'
out=$($CMD | awk "$LANSCAN_AWK $GET_IP4 $GET_IP6 $GET_SPEED_DUPLEX $PRINTF $FILL_BLANKS")
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
echo "$out"
fi
elif [ "$KERNEL" = "FreeBSD" ] ; then
assertHaveCommand ifconfig
assertHaveCommand netstat
CMD_LIST_INTERFACES='ifconfig -a'
# Filters have been applied to get rid of IPv6 addresses designated for special usage to extract only the global IPv6 address.
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) -v IPv6_Address=$(ifconfig -a | grep inet6 | grep -v ' ::1 ' | grep -v ' ::1/' | grep -v ' ::1%' | grep -v ' fe80::' | grep -v ' 2002::' | grep -v ' ff00::' | head -n 1 | xargs | cut -d '/' -f 1 | cut -d '%' -f 1 | cut -d ' ' -f 2)"
# shellcheck disable=SC2016
CHOOSE_ACTIVE='/LOOPBACK/ {next} !/RUNNING/ {next} /^[a-z0-9]+: / {sub(":$", "", $1); print $1}'
UNIQUE='sort -u'
# shellcheck disable=SC2016
GET_MAC='{$1 == "ether" && mac = $2}'
# shellcheck disable=SC2016
GET_IP='/ netmask / {for (i=1; i<=NF; i++) {if ($i == "inet") IPv4 = $(i+1); if ($i == "inet6") IPv6 = $(i+1)}}'
# shellcheck disable=SC2016
GET_SPEED_DUPLEX='/media: / {sub("\134(", "", $4); speed=$4; sub("-duplex.*", "", $5); sub("<", "", $5); duplex=$5}'
# shellcheck disable=SC2016
GET_RXbytes_TXbytes_COLLISIONS_ERRORS='{
if ($0 ~ /Name/)
{
for (i=1; i<=NF; i++)
{
if ($i == "Address") {address_column = i;}
else if ($i == "Ibytes") {ibytes_column = i;}
else if ($i == "Ierrs") {ierrs_column = i;}
else if ($i == "Obytes") {obytes_column = i;}
else if ($i == "Oerrs") {oerrs_column = i;}
else if ($i == "Coll") {coll_column = i;}
}
flag = 1;
}
if(flag == 1){
if ($address_column == mac)
{
(ibytes_column == "") ? RXbytes = "<n/a>" : RXbytes = $(ibytes_column);
(ierrs_column == "") ? RXerrors = "<n/a>" : RXerrors = $(ierrs_column);
(obytes_column == "") ? TXbytes = "<n/a>" : TXbytes = $(obytes_column);
(oerrs_column == "") ? TXerrors = "<n/a>" : TXerrors = $(oerrs_column);
(coll_column == "") ? collisions = "<n/a>" : collisions = $(coll_column);
}
}
}'
FILL_BLANKS='{length(IP_address) || IP_address = "?";length(OS_version) || OS_version = "?";length(OSName) || OSName = "?"; length(IPv6_Address) || IPv6_Address = "?"; length(speed) || speed = "<n/a>"; length(duplex) || duplex = "<n/a>"; IPv4 = IPv4 ? IPv4 : "<n/a>"; IPv6 = IPv6 ? IPv6 : "<n/a>"}'
GET_ALL="$GET_MAC $GET_IP $GET_SPEED_DUPLEX $GET_RXbytes_TXbytes_COLLISIONS_ERRORS $FILL_BLANKS"
out=$($CMD_LIST_INTERFACES | tee "$TEE_DEST" | awk "$CHOOSE_ACTIVE" | $UNIQUE | tee -a "$TEE_DEST")
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 0 ]; then
echo "$HEADER"
fi
for iface in $out
do
echo "Cmd = [$CMD_LIST_INTERFACES]; | awk '$CHOOSE_ACTIVE' | $UNIQUE" >> "$TEE_DEST"
CMD_DESCRIBE_INTERFACE="eval ifconfig $iface ; netstat -b -I $iface"
# shellcheck disable=SC2086
$CMD_DESCRIBE_INTERFACE | tee -a "$TEE_DEST" | awk $DEFINE "$GET_ALL $PRINTF" name="$iface"
echo "Cmd = [$CMD_DESCRIBE_INTERFACE]; | awk $DEFINE '$GET_ALL $PRINTF' name=$iface" >> "$TEE_DEST"
done
fi
# jscpd:ignore-end

52
bin/iostat.sh Executable file
View file

@ -0,0 +1,52 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# suggested command for testing reads: $ find / -type f 2>/dev/null | xargs wc &> /dev/null &
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
if [ "$KERNEL" = "Linux" ] ; then
CMD='iostat -xky 1 1'
assertHaveCommand "$CMD"
# considers the device, r/s and w/s columns and returns output of the first interval
FILTER='/Device/ && /r\/s/ && /w\/s/ {f=1;}f'
elif [ "$KERNEL" = "SunOS" ] ; then
CMD='iostat -xn 1 2'
assertHaveCommand "$CMD"
# considers the device, r/s and w/s columns and returns output of the second interval
FILTER='/device/ && /r\/s/ && /w\/s/ {f++;} f==2'
elif [ "$KERNEL" = "AIX" ] ; then
CMD='iostat 1 2'
assertHaveCommand "$CMD"
# considers the disks, kb_read and kb_wrtn columns and returns output of the second interval
FILTER='/^cd/ {next} /Disks/ && /Kb_read/ && /Kb_wrtn/ {f++;} f==2'
elif [ "$KERNEL" = "FreeBSD" ] ; then
CMD='iostat -x -c 2'
assertHaveCommand "$CMD"
# considers the device, r/s and w/s columns and returns output of the second interval
FILTER='/device/ && /r\/s/ && /w\/s/ {f++;} f==2'
elif [ "$KERNEL" = "Darwin" ] ; then
CMD="eval $SPLUNK_HOME/bin/darwin_disk_stats ; sleep 2; echo Pause; $SPLUNK_HOME/bin/darwin_disk_stats"
# shellcheck disable=SC2086
assertHaveCommandGivenPath $CMD
# shellcheck disable=SC2016
HEADER='Device rReq_PS wReq_PS rKB_PS wKB_PS avgWaitMillis avgSvcMillis bandwUtilPct'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='{printf "%-10s %11s %11s %12s %12s %13s %13s %13s\n", device, rReq_PS, wReq_PS, rKB_PS, wKB_PS, avgWaitMillis, avgSvcMillis, bandwUtilPct}'
# shellcheck disable=SC2016
FILTER='BEGIN {FS="|"; after=0} /^Pause$/ {after=1; next} !/Bytes|Operations/ {next} {devices[$1]=$1; values[after,$1,$2]=$3; next}'
FORMAT='avgSvcMillis=bandwUtilPct="?";'
FUNC1='function getDeltaPS(disk, metric) {delta=values[1,disk,metric]-values[0,disk,metric]; return delta/2.0}'
# Calculates the latency by pulling the read and write latency fields from darwin__disk_stats and evaluating their sum
LATENCY='function getLatency(disk) {read=getDeltaPS(disk,"Latency Time (Read)"); write=getDeltaPS(disk,"Latency Time (Write)"); return expr read + write;}'
FUNC2='function getAllDeltasPS(disk) {rReq_PS=getDeltaPS(disk,"Operations (Read)"); wReq_PS=getDeltaPS(disk,"Operations (Write)"); rKB_PS=getDeltaPS(disk,"Bytes (Read)")/1024; wKB_PS=getDeltaPS(disk,"Bytes (Write)")/1024; avgWaitMillis=getLatency(disk);}'
SCRIPT="$HEADERIZE $FILTER $FUNC1 $LATENCY $FUNC2 END {$FORMAT for (device in devices) {getAllDeltasPS(device); $PRINTF}}"
$CMD | tee "$TEE_DEST" | awk "$SCRIPT" header="$HEADER"
echo "Cmd = [$CMD]; | awk '$SCRIPT' header=\"$HEADER\"" >> "$TEE_DEST"
exit 0
fi
$CMD | tee "$TEE_DEST" | $AWK "$FILTER"
echo "Cmd = [$CMD]; | $AWK '$FILTER'" >> "$TEE_DEST"

67
bin/iostat_metric.sh Executable file
View file

@ -0,0 +1,67 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# suggested command for testing reads: $ find / -type f 2>/dev/null | xargs wc &> /dev/null &
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
if [ "$KERNEL" = "Linux" ] ; then
CMD='iostat -xky 1 1'
assertHaveCommand "$CMD"
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=$(hostname -I | cut -d\ -f1)"
else
DEFINE="-v OSName=$(cat /etc/*release | grep '\bNAME=' | cut -d '=' -f2 | tr ' ' '_' | cut -d\" -f2) -v OS_version=$(cat /etc/*release | grep '\bVERSION_ID=' | cut -d '=' -f2 | cut -d\" -f2) -v IP_address=$(hostname -I | cut -d\ -f1)"
fi
FILTER='/Device/ && /r\/s/ && /w\/s/ {f=1;}f'
# shellcheck disable=SC2016
PRINTF='{if ($0~/Device/) {printf "%s OSName OS_version IP_address \n", $0} else if (NF!=0) {printf "%s %s %s %s\n", $0, OSName, OS_version, IP_address}}'
elif [ "$KERNEL" = "SunOS" ] ; then
CMD='iostat -xn 1 2'
# jscpd:ignore-start
assertHaveCommand "$CMD"
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)"
FILTER='/device/ && /r\/s/ && /w\/s/ {f++;} f==2'
# shellcheck disable=SC2016
PRINTF='{if ($0~/device/ && /r\/s/ && /w\/s/) {printf "%s OSName OS_version IP_address \n", $0} else if (NF!=0) {printf "%s %s %s %s\n", $0, OSName, OS_version, IP_address}}'
# jscpd:ignore-end
elif [ "$KERNEL" = "AIX" ] ; then
CMD='iostat 1 2'
assertHaveCommand "$CMD"
DEFINE="-v OSName=$(uname -s) -v OS_version=$(oslevel -r | cut -d'-' -f1) -v IP_address=$(ifconfig -a | grep 'inet ' | grep -v 127.0.0.1 | cut -d\ -f2 | head -n 1)"
FILTER='/^cd/ {next} /Disks/ && /Kb_read/ && /Kb_wrtn/ {f++;} f==2'
# shellcheck disable=SC2016
PRINTF='{if ($0~/Disks/ && /Kb_read/ && /Kb_wrtn/) {printf "%s OSName OS_version IP_address \n", $0} else if (NF!=0) {printf "%s %s %s %s\n", $0, OSName, OS_version/1000, IP_address}}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
CMD='iostat -x -c 2'
assertHaveCommand "$CMD"
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)"
FILTER='/device/ && /r\/s/ && /w\/s/ {f++;} f==2'
# shellcheck disable=SC2016
PRINTF='{if ($0~/device/ && /r\/s/ && /w\/s/) {printf "%s OSName OS_version IP_address \n", $0} else if (NF!=0) {printf "%s %s %s %s\n", $0, OSName, OS_version, IP_address}}'
elif [ "$KERNEL" = "Darwin" ] ; then
CMD="eval $SPLUNK_HOME/bin/darwin_disk_stats ; sleep 2; echo Pause; $SPLUNK_HOME/bin/darwin_disk_stats"
# shellcheck disable=SC2086
assertHaveCommandGivenPath $CMD
HEADER='Device rReq_PS wReq_PS rKB_PS wKB_PS avgWaitMillis avgSvcMillis bandwUtilPct OSName OS_version IP_address'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='{printf "%-10s %11s %11s %12s %12s %13s %13s %13s %-35s %15s %-16s\n", device, rReq_PS, wReq_PS, rKB_PS, wKB_PS, avgWaitMillis, avgSvcMillis, bandwUtilPct, OSName, OS_version, IP_address}'
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
FILTER='BEGIN {FS="|"; after=0} /^Pause$/ {after=1; next} !/Bytes|Operations/ {next} {devices[$1]=$1; values[after,$1,$2]=$3; next}'
FORMAT='{avgSvcMillis=bandwUtilPct="?";OSName=OSName;OS_version=OS_version;IP_address=IP_address;}'
FUNC1='function getDeltaPS(disk, metric) {delta=values[1,disk,metric]-values[0,disk,metric]; return delta/2.0}'
# Calculates the latency by pulling the read and write latency fields from darwin__disk_stats and evaluating their sum
LATENCY='function getLatency(disk) {read=getDeltaPS(disk,"Latency Time (Read)"); write=getDeltaPS(disk,"Latency Time (Write)"); return expr read + write;}'
FUNC2='function getAllDeltasPS(disk) {rReq_PS=getDeltaPS(disk,"Operations (Read)"); wReq_PS=getDeltaPS(disk,"Operations (Write)"); rKB_PS=getDeltaPS(disk,"Bytes (Read)")/1024; wKB_PS=getDeltaPS(disk,"Bytes (Write)")/1024; avgWaitMillis=getLatency(disk);}'
SCRIPT="$HEADERIZE $FILTER $FUNC1 $LATENCY $FUNC2 END {$FORMAT for (device in devices) {getAllDeltasPS(device); $PRINTF}}"
# shellcheck disable=SC2086
$CMD | tee "$TEE_DEST" | awk $DEFINE "$SCRIPT" header="$HEADER"
echo "Cmd = [$CMD]; | awk $DEFINE '$SCRIPT' header=\"$HEADER\"" >> "$TEE_DEST"
exit 0
fi
# shellcheck disable=SC2086
$CMD | tee "$TEE_DEST" | $AWK $DEFINE "$FILTER $PRINTF"
echo "Cmd = [$CMD]; | $AWK $DEFINE '$FILTER'" >> "$TEE_DEST"

53
bin/lastlog.sh Executable file
View file

@ -0,0 +1,53 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER='USERNAME FROM LATEST'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='{printf "%-30s %-30.30s %-s\n", username, from, latest}'
if [ "$KERNEL" = "Linux" ] ; then
CMD='last -iw'
# shellcheck disable=SC2016
FILTER='{if ($0 == "") exit; if ($1 ~ /reboot|shutdown/ || $1 in users) next; users[$1]=1}'
# shellcheck disable=SC2016
FORMAT='{username = $1; from = (NF==10) ? $3 : "<console>"; latest = $(NF-6) " " $(NF-5) " " $(NF-4) " " $(NF-3)}'
elif [ "$KERNEL" = "SunOS" ] ; then
CMD='last -n 999'
# shellcheck disable=SC2016
FILTER='{if ($0 == "") exit; if ($1 ~ /reboot|shutdown/ || $1 in users) next; users[$1]=1}'
# shellcheck disable=SC2016
FORMAT='{username = $1; from = (NF==10) ? $3 : "<console>"; latest = $(NF-6) " " $(NF-5) " " $(NF-4) " " $(NF-3)}'
elif [ "$KERNEL" = "AIX" ] ; then
failUnsupportedScript
elif [ "$KERNEL" = "Darwin" ] ; then
CMD='last -99'
# shellcheck disable=SC2016
FILTER='{if ($0 == "") exit; if ($1 ~ /reboot|shutdown/ || $1 in users) next; users[$1]=1}'
# shellcheck disable=SC2016
FORMAT='{username = $1; from = ($0 !~ / /) ? $3 : "<console>"; latest = $(NF-6) " " $(NF-5) " " $(NF-4) " " $(NF-3)}'
elif [ "$KERNEL" = "HP-UX" ] ; then
CMD='lastb -Rx'
# shellcheck disable=SC2016
FORMAT='{username = $1; from = ($2=="console") ? $2 : $3; latest = $(NF-3) " " $(NF-2)" " $(NF-1)}'
# shellcheck disable=SC2016
FILTER='{if ($1 == "BTMPS_FILE") next; if (NF==0) next; if (NF<=6) next;}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
CMD='lastlogin'
# shellcheck disable=SC2016
FORMAT='{username = $1; from = (NF==8) ? $3 : "<console>"; latest=$(NF-4) " " $(NF-3) " " $(NF-2) " " $(NF-1) " " $NF}'
fi
assertHaveCommand $CMD
out=$($CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $FILTER $FORMAT $PRINTF" header="$HEADER")
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 1 ]; then
echo "$out"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $FILTER $FORMAT $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"
else
echo "No data is present" >> "$TEE_DEST"
fi

74
bin/lsof.sh Executable file
View file

@ -0,0 +1,74 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
assertHaveCommand lsof
CMD='lsof -nPs +c 0'
# shellcheck disable=SC2016
FILTER='/Permission denied|NOFD|unknown/ {next}'
if [[ "$KERNEL" = "Linux" ]] || [[ "$KERNEL" = "HP-UX" ]] || [[ "$KERNEL" = "Darwin" ]] || [[ "$KERNEL" = "FreeBSD" ]] ; then
if [ "$KERNEL" = "Darwin" ] ; then
# shellcheck disable=SC2016
FILTER='/KQUEUE|PIPE|PSXSEM/ {next}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
if [[ $KERNEL_RELEASE =~ 11.* ]] || [[ $KERNEL_RELEASE =~ 12.* ]] || [[ $KERNEL_RELEASE =~ 13.* ]]; then
# empty condition to allow the execution of script as is
echo > /dev/null
else
failUnsupportedScript
fi
fi
else
failUnsupportedScript
fi
PARSE_0='NR == 1 {
# Extract positions and headers from the first line
for (i = 1; i <= NF; i++) {
positions[i] = index($0, $i)
headers[i] = length($i)
if (i == NF) {
printf "%s", $i
}
else {
printf "%10s ", $i
}
}
printf "\n"
next
}'
PARSE_1='{
id = 1
for (i = 1; i <= length(positions); i++) {
if (i == length(positions)) {
field = substr($0, positions[i])
} else {
field = substr($0, positions[i], headers[i])
}
if (field ~ /^ *$/) {
field = "?"
id--
} else {
field = $id
}
id = id + 1
if (i == length(positions)) {
printf "%s", field
}
else {
printf "%10s ", field
}
}
printf "\n"
}
'
assertHaveCommand "$CMD"
# shellcheck disable=SC2094
$CMD 2>"$TEE_DEST" | tee "$TEE_DEST" | awk "$FILTER $PARSE_0 $PARSE_1"
echo "Cmd = [$CMD 2>$TEE_DEST]; | awk -v positions=\"$positions\" -v headers=\"$headers\" \"$FILTER $PRINTF\"" >> "$TEE_DEST"

52
bin/netstat.sh Executable file
View file

@ -0,0 +1,52 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER='Proto Recv-Q Send-Q LocalAddress ForeignAddress State'
HEADERIZE="BEGIN {print \"$HEADER\"}"
# shellcheck disable=SC2016
PRINTF='{printf "%-5s %6s %6s %-30.30s %-30.30s %-s\n", $1, $2, $3, $4, $5, $6}'
# shellcheck disable=SC2016
FILL_BLANKS='($1=="udp") {$6="<n/a>"}'
if [ "$KERNEL" = "Linux" ] ; then
queryHaveCommand ss
FOUND_SS=$?
if [ $FOUND_SS -eq 0 ] ; then
CMD='eval ss -antu 2>/dev/null | egrep "tcp|udp"'
# shellcheck disable=SC2016
FORMAT='{ state=$2; $2=$3; $3=$4; $4=$5; $5=$6; $6=state}'
else
CMD='eval netstat -aenp 2>/dev/null | egrep "tcp|udp"'
fi
elif [ "$KERNEL" = "SunOS" ] ; then
CMD='netstat -an -f inet -f inet6'
FIGURE_SECTION='NR==1 {inUDP=1;inTCP=0} /^TCP: IPv/ {inUDP=0;inTCP=1} /^SCTP:/ {exit}'
FILTER='/: IPv|Local Address|^$|^-----/ {next}'
# shellcheck disable=SC2016
FORMAT_UDP='(inUDP) {localAddr=$1; $1="udp"; $2=$3=0; $4=localAddr; $5="*.*"}'
# shellcheck disable=SC2016
FORMAT_TCP='(inTCP) {localAddr=$1; foreignAddr=$2; sendQ=$4; recvQ=$6; state=$7; $1="tcp"; $2=recvQ; $3=sendQ; $4=localAddr; $5=foreignAddr; $6=state}'
FORMAT="$FORMAT_UDP $FORMAT_TCP"
elif [ "$KERNEL" = "AIX" ] ; then
CMD='eval netstat -an 2>/dev/null | egrep "tcp|udp"'
elif [ "$KERNEL" = "Darwin" ] ; then
CMD='eval netstat -anW | egrep "tcp|udp"'
# shellcheck disable=SC2016
FORMAT='{gsub("[46]", "", $1)}'
elif [ "$KERNEL" = "HP-UX" ] ; then
CMD='eval netstat -an | egrep "tcp|udp"'
elif [ "$KERNEL" = "FreeBSD" ] ; then
# shellcheck disable=SC2089
CMD='eval netstat -an | egrep "tcp|udp"'
# shellcheck disable=SC2016
FORMAT='{gsub("[46]", "", $1)}'
fi
assertHaveCommand "$CMD"
# shellcheck disable=SC2090
$CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $FIGURE_SECTION $FILTER $FORMAT $FILL_BLANKS $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $FIGURE_SECTION $FILTER $FORMAT $FILL_BLANKS $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"

199
bin/nfsiostat.sh Executable file
View file

@ -0,0 +1,199 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER='Mount Path r_op/s w_op/s r_KB/s w_KB/s rpc_backlog r_avg_RTT w_avg_RTT r_avg_exe w_avg_exe'
HEADERIZE="BEGIN {print \"$HEADER\"}"
# We can have the multiple mounts for the nfs. So we have to parse mount separately.
# For CentOS and RHEL the number of lines for each mount is 9, while for the ubuntu it is 22
# due to the bug mentioned in this link. https://bugs.launchpad.net/ubuntu/+source/nfs-utils/+bug/1584719
# So, we are handling the case of Ubuntu separately.
# When awk iterates through each line, using modulo operator we are checking the line number
# And extracting the particular value from that line and assigning it to the variable
# which we will use when the output of modulo is 0 as it will be the last line of that mount.
# We are also removing last character in the line "path=substr($4, 1, length($4)-1)"
# as last character of the path is ":"
if [ "$KERNEL" = "Linux" ] ; then
OS_FILE=/etc/os-release
if echo "$OS_ID" | grep -qi suse; then
CMD='/usr/sbin/nfsiostat'
assertHaveCommandGivenPath $CMD
else
CMD='nfsiostat'
assertHaveCommand $CMD
fi
no_of_lines=$($CMD| wc -l)
# If there are no mount, exit
if [ "$no_of_lines" -eq 1 ];
then
$CMD >> "$TEE_DEST"
exit 1
fi
# Below condition is added to handle the case of Ubuntu OS
if [ -e $OS_FILE ] && (awk -F'=' '/ID=/ {print $2}' $OS_FILE | grep -q ubuntu);
then
# shellcheck disable=SC2016
OS_RELEASE=$($AWK -F= '/VERSION_ID=/ {print $2}' $OS_FILE)
if [ "$OS_RELEASE" = "\"18.04\"" ] || [ "$OS_RELEASE" = "\"20.04\"" ] || [ "$OS_RELEASE" = "\"22.04\"" ] ; then # Ubuntu 18.04, 20.04 and 22.04
# shellcheck disable=SC2016
FORMAT='{
if (NR%10==2){
echo "device"
device=$1
path=substr($4, 1, length($4)-1)
}
else if (NR%10==5){
rpc_backlog=$2
}
else if (NR%10==8){
r_op_s=$1
r_kb_s=$2
r_avg_rtt=$6
r_avg_exe=$7
}
else if (NR%10==0){
w_op_s=$1
w_kb_s=$2
w_avg_rtt=$6
w_avg_exe=$7
printf "%s %s %s %s %s %s %s %s %s %s %s\n",device, path, r_op_s, w_op_s, r_kb_s, w_kb_s, rpc_backlog, r_avg_rtt, w_avg_rtt, r_avg_exe, w_avg_exe
}
}'
else
# shellcheck disable=SC2016
FORMAT='{
if (NR%22==2){
echo "device"
device=$1
path=substr($4, 1, length($4)-1)
}
else if (NR%22==6){
rpc_backlog=$1
}
else if (NR%22==9){
r_op_s=$1
}
else if (NR%22==10){
r_kb_s=$1
}
else if (NR%22==13){
r_avg_rtt=$1
}
else if (NR%22==14){
r_avg_exe=$1
}
else if (NR%22==17){
w_op_s=$1
}
else if (NR%22==18){
w_kb_s=$1
}
else if (NR%22==21){
w_avg_rtt=$1
}
else if (NR%22==0){
w_avg_exe=$1
printf "%s %s %s %s %s %s %s %s %s %s %s\n",device, path, r_op_s, w_op_s, r_kb_s, w_kb_s, rpc_backlog, r_avg_rtt, w_avg_rtt, r_avg_exe, w_avg_exe
}
}'
fi
# For SUSE OS
elif echo "$OS_ID" | grep -qi suse;
then
FORMAT='{
if (NR%10==2){
device=$1
path=substr($4, 1, length($4)-1)
}
else if (NR%10==5){
rpc_backlog=$2
}
else if (NR%10==8){
r_op_s=$1
r_kb_s=$2
r_avg_rtt=$6
r_avg_exe=$7
}
else if (NR%10==0){
w_op_s=$1
w_kb_s=$2
w_avg_rtt=$6
w_avg_exe=$7
printf "%s %s %s %s %s %s %s %s %s %s %s\n",device, path, r_op_s, w_op_s, r_kb_s, w_kb_s, rpc_backlog, r_avg_rtt, w_avg_rtt, r_avg_exe, w_avg_exe
}
}'
# For CentOS and RHEL
else
#For RHEL 8.x
if [ -e $OS_FILE ] && ( ( (awk -F'=' '/ID=/ {print $2}' $OS_FILE | grep -q rhel) && (awk -F'=' '/VERSION_ID=/ {print $2}' $OS_FILE | grep -Eq 8.7\|8.6\|8.5\|8.4\|8.3\|9) ) || ( (awk -F'=' '/ID=/ {print $2}' $OS_FILE | grep -q cent) && (awk -F'=' '/VERSION_ID=/ {print $2}' $OS_FILE | grep -Eq 8) ) );
then
# shellcheck disable=SC2016
FORMAT='{
if (NR%10==2){
device=$1
path=substr($4, 1, length($4)-1)
}
else if (NR%10==5){
rpc_backlog=$2
}
else if (NR%10==8){
r_op_s=$1
r_kb_s=$2
r_avg_rtt=$6
r_avg_exe=$7
}
else if (NR%10==0){
w_op_s=$1
w_kb_s=$2
w_avg_rtt=$6
w_avg_exe=$7
printf "%s %s %s %s %s %s %s %s %s %s %s\n",device, path, r_op_s, w_op_s, r_kb_s, w_kb_s, rpc_backlog, r_avg_rtt, w_avg_rtt, r_avg_exe, w_avg_exe
}
}'
else
# shellcheck disable=SC2016
FORMAT='{
if (NR%9==2){
device=$1
path=substr($4, 1, length($4)-1)
}
else if (NR%9==5){
rpc_backlog=$2
}
else if (NR%9==7){
r_op_s=$1
r_kb_s=$2
r_avg_rtt=$6
r_avg_exe=$7
}
else if (NR%9==0){
w_op_s=$1
w_kb_s=$2
w_avg_rtt=$6
w_avg_exe=$7
printf "%s %s %s %s %s %s %s %s %s %s %s\n",device, path, r_op_s, w_op_s, r_kb_s, w_kb_s, rpc_backlog, r_avg_rtt, w_avg_rtt, r_avg_exe, w_avg_exe
}
}'
fi
fi
$CMD | tee "$TEE_DEST" | awk "$HEADERIZE $FORMAT" | column -t
echo "Cmd = [$CMD]; | awk '$HEADERIZE $FORMAT' header=\"$HEADER\"" >> "$TEE_DEST"
else
failUnsupportedScript
fi

66
bin/openPorts.sh Executable file
View file

@ -0,0 +1,66 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# a similar effect can be accomplished with: "nc -z 127.0.0.1 1-32768", and "nc -zu 127.0.0.1 1-32768"
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER='Proto Port'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='{printf "%-5s %5d\n", proto, port}'
# shellcheck disable=SC2016
FILTER_INACTIVE='($NF ~ /^CLOSE/) {next}'
if [ "$KERNEL" = "Linux" ] ; then
queryHaveCommand ss
FOUND_SS=$?
if [ $FOUND_SS -eq 0 ] ; then
CMD='eval ss -lnut | egrep "^tcp|^udp"'
# shellcheck disable=SC2016
FORMAT='{proto=$1; sub("^.*:", "", $5); port=$5}'
else
CMD='eval netstat -ln | egrep "^tcp|^udp"'
# shellcheck disable=SC2016
FORMAT='{proto=$1; sub("^.*:", "", $4); port=$4}'
fi
elif [ "$KERNEL" = "SunOS" ] ; then
CMD='netstat -an -f inet -f inet6'
FIGURE_SECTION='BEGIN {inUDP=1;inTCP=0} /^TCP: IPv/ {inUDP=0;inTCP=1} /^SCTP:/ {exit}'
FILTER='/: IPv|Local Address|^$|^-----/ {next} (! port) {next}'
# shellcheck disable=SC2016
FORMAT='{if (inUDP) proto="udp"; if (inTCP) proto="tcp"; sub("^.*[^0-9]", "", $1); port=$1}'
elif [ "$KERNEL" = "AIX" ] ; then
CMD='eval netstat -an | egrep "^tcp|^udp"'
HEADERIZE="BEGIN {print \"$HEADER\"}"
# shellcheck disable=SC2016
FORMAT='{gsub("[46]", "", $1); proto=$1; sub("^.*[^0-9]", "", $4); port=$4}'
# shellcheck disable=SC2016
FILTER='{if ($4 == "") next}'
elif [ "$KERNEL" = "Darwin" ] ; then
CMD='eval netstat -ln | egrep "^tcp|^udp"'
HEADERIZE="BEGIN {print \"$HEADER\"}"
# shellcheck disable=SC2016
FORMAT='{gsub("[46]", "", $1); proto=$1; sub("^.*[^0-9]", "", $4); port=$4}'
# shellcheck disable=SC2016
FILTER='{if ($4 == "") next}'
elif [ "$KERNEL" = "HP-UX" ] ; then
CMD='eval netstat -an | egrep "^tcp|^udp"'
HEADERIZE="BEGIN {print \"$HEADER\"}"
# shellcheck disable=SC2016
FORMAT='{gsub("[46]", "", $1); proto=$1; sub("^.*[^0-9]", "", $4); port=$4}'
# shellcheck disable=SC2016
FILTER='{if ($4 == "") next}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
# shellcheck disable=SC2089
CMD='eval netstat -ln | egrep "^tcp|^udp"'
HEADERIZE="BEGIN {print \"$HEADER\"}"
# shellcheck disable=SC2016
FORMAT='{gsub("[46]", "", $1); proto=$1; sub("^.*[^0-9]", "", $4); port=$4}'
fi
assertHaveCommand "$CMD"
# shellcheck disable=SC2090
$CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $FIGURE_SECTION $FORMAT $FILTER $FILTER_INACTIVE $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $FIGURE_SECTION $FORMAT $FILTER $FILTER_INACTIVE $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"

125
bin/openPortsEnhanced.sh Executable file
View file

@ -0,0 +1,125 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
# In AWK scripts in this file, the following are true:
# FULLTEXT is used to capture the output for SHA256 checksum generation.
# SPLUNKD is used to determine Splunk service status.
if [ "$KERNEL" = "Linux" ] || [ "$KERNEL" = "Darwin" ] ; then
assertHaveCommand date
assertHaveCommand lsof
if [ -f /usr/sbin/lsof ] ; then
LSOF=/usr/sbin/lsof
elif [ -f /usr/bin/lsof ] ; then
# shellcheck disable=SC2034
LSOF=/usr/bin/lsof
fi
# shellcheck disable=SC2016
CMD='eval date ; ${LSOF} -i -P -n +c 0'
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0 ; FULLTEXT=""}'
# Only base the file hash on the listening ports, not on
# open connections.
# shellcheck disable=SC2016
PARSE_1='/LISTEN|[Uu][Dd][Pp]/ {
FULLTEXT = FULLTEXT $0 "\n"
idx=match($0, /\(LISTEN\)/)
if (idx>0) {
DATA=substr($0, 0, idx-1)
} else {
DATA=$0
}
fields = split(DATA, portarr)
# This compensates for varying field counts.
if (fields == 9) {
hostfields = split(portarr[9], hostarr, ":")
TRANSPORT="transport=" portarr[8]
} else if (fields == 8) {
hostfields = split(portarr[8], hostarr, ":")
TRANSPORT="transport=" portarr[7]
}
if (hostfields == 2 && hostarr[2] ~ /[0-9][0-9]*/) {
DESTIP="dest_ip=" hostarr[1]
DESTPORT="dest_port=" hostarr[2]
APP="app=" portarr[1]
PID="pid=" portarr[2]
USER="user=" portarr[3]
FD="fd=" portarr[4]
IPVERSION="ip_version=" substr(portarr[5],index(portarr[5],"v")+1)
DVCID="dvc_id=" portarr[6]
#printf "MATCH: %s\n", $0
printf "%s %s %s %s %s %s %s %s %s %s\n", DATE, APP, DESTIP, DESTPORT, PID, USER, FD, IPVERSION, DVCID, TRANSPORT
} else {
#printf "NOMATCH: %s\n", $0
;
}
}'
MASSAGE="$PARSE_0 $PARSE_1"
# Send the collected full text to openssl; this avoids any timing discrepancies
# between when the information is collected and when we process it.
# shellcheck disable=SC2016
POSTPROCESS='END {
printf "%s %s", DATE, "file_hash="
printf "%s", FULLTEXT | "LD_LIBRARY_PATH=$SPLUNK_HOME/lib $SPLUNK_HOME/bin/openssl sha256"
}'
elif [ "$KERNEL" = "SunOS" ] ; then
assertHaveCommand date
assertHaveCommand netstat
CMD='eval date ; netstat -an -f inet -f inet6'
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0 ; FULLTEXT=""}'
# shellcheck disable=SC2016
PARSE_1='/^[Tt][Cc][Pp]|[Uu][Dd][Pp]/ {
split($0, protoarr, ":")
TRANSPORT="transport=" protoarr[1]
IPVERSION="ip_version=" substr(protoarr[2],index(protoarr[2],"v")+1)
next
}'
# shellcheck disable=SC2016
PARSE_3='NR>1 && $0 !~ /Local|^-|^$/ {
FULLTEXT = FULLTEXT $0 "\n"
split($0, arr)
num = split(arr[1], hostarr, "\.")
if ( TRANSPORT ~ /[Tt][Cc][Pp]/) {
DESTIP="dest_ip="hostarr[1]
} else {
DESTIP="dest_dns="hostarr[1]
}
DESTPORT=hostarr[num]
for (i=2; i<num; i++) {
DESTIP=DESTIP"."hostarr[i]
}
if ( $0 !~ /[Uu][Nn][Bb][Oo][Uu][Nn][Dd]/ && DESTPORT != "*" ) {
DESTPORT="dest_port="DESTPORT
printf "%s %s %s %s %s \n", DATE, DESTIP, DESTPORT, IPVERSION, TRANSPORT
}
}'
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_3"
# Send the collected full text to openssl; this avoids any timing discrepancies
# between when the information is collected and when we process it.
# shellcheck disable=SC2016
POSTPROCESS='END {
printf "%s %s", DATE, "file_hash="
printf "%s", FULLTEXT | "LD_LIBRARY_PATH=$SPLUNK_HOME/lib $SPLUNK_HOME/bin/openssl sha256"
}'
else
# Exits
failUnsupportedScript
fi
$CMD | tee "$TEE_DEST" | $AWK "$MASSAGE $POSTPROCESS"
echo "Cmd = [$CMD]; | $AWK '$MASSAGE $POSTPROCESS'" >> "$TEE_DEST"

67
bin/package.sh Executable file
View file

@ -0,0 +1,67 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER='NAME VERSION RELEASE ARCH VENDOR GROUP'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='{printf "%-55.55s %-20.20s %-20.20s %-10.10s %-30.30s %-20s\n", name, version, release, arch, vendor, group}'
CMD='echo There is no flavor-independent command...'
if [ "$KERNEL" = "Linux" ] ; then
if $DEBIAN; then
CMD1="eval dpkg-query -W -f='"
# shellcheck disable=SC2016
CMD2='${Package} ${Version} ${Architecture} ${Homepage}\n'
CMD3="'"
CMD=$CMD1$CMD2$CMD3
# shellcheck disable=SC2016
FORMAT='{name=$1;version=$2;sub("\\.?[^0-9\\.:\\-].*$", "", version); release=$2; sub("^[0-9\\.:\\-]*","",release); if(release=="") {release="?"}; arch=$3; if (NF>3) {sub("^.*:\\/\\/", "", $4); sub("^www\\.", "", $4); sub("\\/.*$", "", $4); vendor=$4} else {vendor="?"} group="?"}'
else
CMD='eval rpm --query --all --queryformat "%-56{name} %-21{version} %-21{release} %-11{arch} %-31{vendor} %-{group}\n"'
# shellcheck disable=SC2016
PRINTF='{print $0}'
fi
elif [ "$KERNEL" = "SunOS" ] ; then
CMD='pkginfo -l'
# shellcheck disable=SC2016
FORMAT='/PKGINST:/ {name=$2 ":"} /NAME:/ {for (i=2;i<=NF;i++) name = name " " $i} /CATEGORY:/ {group=$2} /ARCH:/ {arch=$2} /VERSION:/ {split($2,a,",REV="); version=a[1]; release=a[2]} /VENDOR:/ {vendor=$2; for(i=3;i<=NF;i++) vendor = vendor " " $i}'
SEPARATE_RECORDS='!/^$/ {next} {release = release ? release : "?"}'
elif [ "$KERNEL" = "AIX" ] ; then
CMD='eval lslpp -icq | sed "s,:, ," | sed "s,:.*,,"'
# shellcheck disable=SC2016
FORMAT='{name=$2 ; version=$3 ; vendor=release=arch=group="?"}'
elif [ "$KERNEL" = "Darwin" ] ; then
CMD='system_profiler SPApplicationsDataType'
FILTER='{ if (NR<3) next}'
# shellcheck disable=SC2016
FORMAT='{gsub("[^\40-\176]", "", $0)} /:$/ {sub("^[ ]*", "", $0); sub(":$", "", $0); name=$0} /Last Modified: / {vendor=""} /Version: / {version=$2} /Kind: / {arch=$2} /Get Info String: / {sub("^.*: ", "", $0); sub("[Aa]ll [Rr]ights.*$", "", $0); sub("^.*[Cc]opyright", "", $0); sub("^[^a-zA-Z_]*[0-9][0-9[0-9][0-9]", "", $0); sub("^[ ]*", "", $0); vendor=$0}'
SEPARATE_RECORDS='!/Location:/ {next} {release = "?"; vendor = vendor ? vendor : "?"; group = "?"}'
elif [ "$KERNEL" = "HP-UX" ] ; then
assertHaveCommand swlist
CMD='swlist -a revision -a architecture -a vendor_tag'
# shellcheck disable=SC2016
FILTER='/^#/ {next} $1=="" {next}'
# shellcheck disable=SC2016
FORMAT='{release="?"; group="?"; vendor="?"; name=$1; version=$2; arch=$3} NF==4 {vendor=$4}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
# the below syntax is valid when using zsh, bash, ksh
if [[ $KERNEL_RELEASE =~ 10.* ]] || [[ $KERNEL_RELEASE =~ 11.* ]] || [[ $KERNEL_RELEASE =~ 12.* ]] || [[ $KERNEL_RELEASE =~ 13.* ]]; then
CMD='eval pkg info --raw --all | grep "^name:\|^version:\|^arch:" | cut -d\" -f2'
HEADER='NAME VERSION ARCH '
HEADERIZE="BEGIN {print \"$HEADER\"}"
# shellcheck disable=SC2016
PRINTF='{ printf "%-50.50s" (NR%3==0 ? RS:FS),$1}'
else
CMD='pkg_info -da'
# shellcheck disable=SC2016
FORMAT='/^Information for / {vendor=""; sub(":$", "", $3); name=$3} /^WWW: / {sub("^.*//", "", $2); sub("/.*$", "", $2); sub("^www\134.", "", $2); vendor=$2} /^$/ {blanks+=1} !/^$/ {blanks=0}'
SEPARATE_RECORDS='(blanks<3) {next} {vendor = vendor ? vendor : "?"; version=release=arch=group="?"}'
fi
fi
assertHaveCommand "$CMD"
$CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $FILTER $FORMAT $SEPARATE_RECORDS $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $FILTER $FORMAT $SEPARATE_RECORDS $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"

30
bin/passwd.sh Executable file
View file

@ -0,0 +1,30 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
PRINTF='END {printf "%s %s\n", DATE, FILEHASH}'
# shellcheck disable=SC2034
PASSWD_FILE=/etc/passwd
if [ "$KERNEL" = "Linux" ] || [ "$KERNEL" = "SunOS" ] || [ "$KERNEL" = "AIX" ] || [ "x$KERNEL" != "xHP-UX" ] || [ "$KERNEL" = "Darwin" ] || [ "$KERNEL" = "FreeBSD" ] ; then
assertHaveCommand date
# shellcheck disable=SC2016
CMD='eval date ; eval LD_LIBRARY_PATH=$SPLUNK_HOME/lib $SPLUNK_HOME/bin/openssl sha256 $PASSWD_FILE ; cat $PASSWD_FILE'
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0}'
# shellcheck disable=SC2016
PARSE_1='NR==2 {FILEHASH="file_hash=" $2}'
# Note the inline print in the next PARSE statement.
# Comments are eliminated from the output, but included in FILEHASH.
# shellcheck disable=SC2016
PARSE_2='NR>2 && /^[^#]/ { split($0, arr, ":") ; printf "%s user=%s password=x user_id=%s user_group_id=%s home=%s shell=%s\n", DATE, arr[1], arr[3], arr[4], arr[6], arr[7]}'
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_2"
fi
$CMD | tee "$TEE_DEST" | $AWK "$MASSAGE $PRINTF"
echo "Cmd = [$CMD]; | $AWK '$MASSAGE $PRINTF'" >> "$TEE_DEST"

81
bin/protocol.sh Executable file
View file

@ -0,0 +1,81 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
CMD='netstat -s'
HEADER=' IPdropped TCPrexmits TCPreorder TCPpktRecv TCPpktSent UDPpktLost UDPunkPort UDPpktRecv UDPpktSent'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='END {printf " %10d %10d %10d %10d %10d %10d %10d %10d %10d\n", IPdropped, TCPrexmits, TCPreorder, TCPpktRecv, TCPpktSent, UDPpktLost, UDPunkPort, UDPpktRecv, UDPpktSent}'
OS_FILE=/etc/os-release
if [ "$KERNEL" = "Linux" ] ; then
if echo "$OS_ID" | grep -qi suse; then
# shellcheck disable=SC2016
CMD='nstat -az'
# shellcheck disable=SC2016
TCPreorder=0
FIGURE_SECTION='/^IpOutDiscards/ {IPdropped=$2} /^TcpInSegs/ {TCPpktRecv=$2} /^TcpOutSegs/ {TCPpktSent=$2} /^TcpRetransSegs/ {TCPrexmits=$2} /^UdpInDatagrams/ {UDPpktRecv=$2} /^UdpNoPorts/ {UDPunkPort=$2} /^UdpInErrors/ {UDPpktLost=$2} /^UdpOutDatagrams/ {UDPpktSent=$2} /^.*Reorder/ {TCPreorder+=$2}'
else
# shellcheck disable=SC2016
FIGURE_SECTION='/^Ip:$/ {inIP=1;inTCP=0;inUDP=0} /^Tcp(Ext)?:$/ {inIP=0;inTCP=1;inUDP=0} /^Udp:$/ {inIP=0;inTCP=0;inUDP=1} {if (NF==1 && $1 !~ /^Ip:$|^Udp:$|^Tcp(Ext)?:$/) inIP=inTCP=inUDP=0}'
# shellcheck disable=SC2016
SECTION_IP='inIP && /outgoing packets dropped/ {IPdropped=$1}'
# shellcheck disable=SC2016
SECTION_TCP='inTCP && /segments retransmited/ {TCPrexmits=$1} inTCP && /Detected reordering/ {TCPreorder=$3} inTCP && /[0-9] segments received$/ {TCPpktRecv=$1} inTCP && /segments send out/ {TCPpktSent=$1}'
# shellcheck disable=SC2016
SECTION_UDP='inUDP && /packets received/ {UDPpktRecv=$1} inUDP && /packets sent/ {UDPpktSent=$1} inUDP && /packet receive errors/ {UDPpktLost=$1} inUDP && /packets to unknown port received/ {UDPunkPort=$1}'
fi
elif [ "$KERNEL" = "SunOS" ] ; then
# shellcheck disable=SC2016
COMMON='{gsub("=", "", $0)}'
# shellcheck disable=SC2016
SECTION_IP='/ipOutDiscards/ {IPdropped+=$2} /ipOutNoRoutes/ {IPdropped+=$4} /ipv6OutNoRoutes/ {IPdropped+=$2} /ipv6OutDiscards/ {IPdropped+=$4}'
# shellcheck disable=SC2016
SECTION_TCP='/tcpRetransSegs/ {TCPrexmits=$2} /tcpInUnorderSegs/ {TCPreorder=$2} /tcpInSegs/ {TCPpktRecv=$2} /tcpOutSegs/ {TCPpktSent=$4}'
# shellcheck disable=SC2016
SECTION_UDP='/udpOutErrors/ {UDPpktLost=$4} /udpInErrors/ {UDPunkPort=$5} /udpInDatagrams/ {UDPpktRecv=$3} /udpOutDatagrams/ {UDPpktSent=$2}'
elif [ "$KERNEL" = "AIX" ] ; then
# shellcheck disable=SC2016
FIGURE_SECTION='/^ip:$/ {inIP=1;inTCP=0;inUDP=0} /^tcp:$/ {inIP=0;inTCP=1;inUDP=0} /^udp:$/ {inIP=0;inTCP=0;inUDP=1} {if (NF==1 && $1 !~ /^ip:$|^udp:$|^tcp:$/) inIP=inTCP=inUDP=0}'
# shellcheck disable=SC2016
SECTION_IP='inIP && /output packets? (dropped|discarded)/ {IPdropped+=$1}'
# shellcheck disable=SC2016
SECTION_TCP='inTCP && /data packet.* bytes\) retransmitted$/ {TCPrexmits=$1} inTCP && /out-of-order packets?/ {TCPreorder=$1} inTCP && /packets? received$/ {TCPpktRecv=$1} inTCP && /packets? sent/ {TCPpktSent=$1}'
# shellcheck disable=SC2016
SECTION_UDP='inUDP && /datagrams? received$/ {UDPpktRecv=$1} inUDP && /datagrams? output$/ {UDPpktSent=$1} inUDP && /dropped due to full socket buffers$/ {UDPpktLost=$1} inUDP && /dropped due to no socket$/ {UDPunkPort=$1}'
elif [ "$KERNEL" = "Darwin" ] ; then
# shellcheck disable=SC2016
FIGURE_SECTION='/^ip:$/ {inIP=1;inTCP=0;inUDP=0} /^tcp:$/ {inIP=0;inTCP=1;inUDP=0} /^udp:$/ {inIP=0;inTCP=0;inUDP=1} {if (NF==1 && $1 !~ /^ip:$|^udp:$|^tcp:$/) inIP=inTCP=inUDP=0}'
# shellcheck disable=SC2016
SECTION_IP='inIP && /output packets? (dropped|discarded)/ {IPdropped+=$1}'
# shellcheck disable=SC2016
SECTION_TCP='inTCP && /data packets? .* retransmitted/ {TCPrexmits=$1} inTCP && /out-of-order packets?/ {TCPreorder=$1} inTCP && /packets? received$/ {TCPpktRecv=$1} inTCP && /packets? sent/ {TCPpktSent=$1}'
# shellcheck disable=SC2016
SECTION_UDP='inUDP && /datagrams? received$/ {UDPpktRecv=$1} inUDP && /datagrams? output$/ {UDPpktSent=$1} inUDP && /dropped due to full socket buffers$/ {UDPpktLost=$1} inUDP && /dropped due to no socket$/ {UDPunkPort=$1}'
elif [ "$KERNEL" = "HP-UX" ] ; then
# shellcheck disable=SC2016
FIGURE_SECTION='/^ip:$/ {inIP=1;inTCP=0;inUDP=0} /^tcp(Ext)?:$/ {inIP=0;inTCP=1;inUDP=0} /^udp:$/ {inIP=0;inTCP=0;inUDP=1} {if (NF==1 && $1 !~ /^ip:$|^udp:$|^tcp(Ext)?:$/) inIP=inTCP=inUDP=0}'
# shellcheck disable=SC2016
SECTION_IP='inIP && /fragments dropped/ {IPdropped=$1}'
# shellcheck disable=SC2016
SECTION_TCP='inTCP && /retransmited$/ {TCPrexmits=$1} inTCP && /out of order/ {TCPreorder=$1} inTCP && /[0-9] packets received$/ {TCPpktRecv=$1} inTCP && /[0-9] packets sent$/ {TCPpktSent=$1}'
# shellcheck disable=SC2016
SECTION_UDP='inUDP && /packets received/ {UDPpktRecv=$1} inUDP && /packets sent/ {UDPpktSent=$1} inUDP && /packet receive errors/ {UDPpktLost=$1} inUDP && /packets to unknown port received/ {UDPunkPort=$1}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
# shellcheck disable=SC2016
FIGURE_SECTION='/^ip:$/ {inIP=1;inTCP=0;inUDP=0} /^tcp:$/ {inIP=0;inTCP=1;inUDP=0} /^udp:$/ {inIP=0;inTCP=0;inUDP=1} {if (NF==1 && $1 !~ /^ip:$|^udp:$|^tcp:$/) inIP=inTCP=inUDP=0}'
# shellcheck disable=SC2016
SECTION_IP='inIP && /output packets? (dropped|discarded)/ {IPdropped+=$1}'
# shellcheck disable=SC2016
SECTION_TCP='inTCP && /data packet.* bytes\) retransmitted$/ {TCPrexmits=$1} inTCP && /out-of-order packets?/ {TCPreorder=$1} inTCP && /packets? received$/ {TCPpktRecv=$1} inTCP && /packets? sent/ {TCPpktSent=$1}'
# shellcheck disable=SC2016
SECTION_UDP='inUDP && /datagrams? received$/ {UDPpktRecv=$1} inUDP && /datagrams? output$/ {UDPpktSent=$1} inUDP && /dropped due to full socket buffers$/ {UDPpktLost=$1} inUDP && /dropped due to no socket$/ {UDPunkPort=$1}'
fi
assertHaveCommand "$CMD"
$CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $FIGURE_SECTION $COMMON $SECTION_IP $SECTION_TCP $SECTION_UDP $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $FIGURE_SECTION $COMMON $SECTION_IP $SECTION_TCP $SECTION_UDP $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"

76
bin/ps.sh Executable file
View file

@ -0,0 +1,76 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
# shellcheck disable=SC2166
if [ "$KERNEL" = "Linux" -o "$KERNEL" = "Darwin" -o "$KERNEL" = "FreeBSD" ] ; then
assertHaveCommand ps
CMD='ps auxww'
elif [ "$KERNEL" = "AIX" ] ; then
assertHaveCommandGivenPath /usr/sysv/bin/ps
CMD='/usr/sysv/bin/ps -eo user,pid,psr,pcpu,time,pmem,rss,vsz,tty,s,etime,args'
elif [ "$KERNEL" = "SunOS" ] ; then
assertHaveCommandGivenPath /usr/bin/ps
CMD='/usr/bin/ps -eo user,pid,psr,pcpu,time,pmem,rss,vsz,tty,s,etime,args'
elif [ "$KERNEL" = "HP-UX" ] ; then
HEADER='USER PID PSR pctCPU CPUTIME pctMEM RSZ_KB VSZ_KB TTY S ELAPSED COMMAND ARGS'
# shellcheck disable=SC2016
FORMAT='{sub("^_", "", $1); if (NF>12) {args=$13; for (j=14; j<=NF; j++) args = args "_" $j} else args="<noArgs>"; sub("^[^\134[: -]*/", "", $12)}'
# shellcheck disable=SC2016
PRINTF='{if (NR == 1) {print $0} else {printf "%32.32s %6s %4s %6s %12s %6s %8s %8s %-7.7s %1.1s %12s %-100.100s %s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, args}}'
# shellcheck disable=SC2016
HEADERIZE='{NR == 1 && $0 = header}'
assertHaveCommand ps
export UNIX95=1
CMD='ps -e -o ruser,pid,pset,pcpu,time,vsz,tty,state,etime,args'
# shellcheck disable=SC2016
FORMAT='{sub("^_", "", $1); if (NF>12) {args=$13; for (j=14; j<=NF; j++) args = args "_" $j} else args="<noArgs>"; sub("^[\[\]]", "", $11)}'
# shellcheck disable=SC2016
PRINTF='{if (NR == 1) {print $0} else {printf "%-14.14s %6s %4s %6s %12s %6s %8s %8s %-7.7s %1.1s %12s %-18.18s %s\n", $1, $2, $3, $4, $5, "?", "?", $6, $7, $8, $9, $10, $11, arg}}'
$CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $FORMAT $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $FORMAT $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"
exit
fi
# shellcheck disable=SC2016
# awk logic for adding extra field ARGS with underscore delimiter
ARGS_FORMAT='BEGIN {OFS = " ";} # specify output field separator
{
if (NR == 1) # Add extra header/field ARGS in first (header) row
{
command_column = NF;
$(NF+1) = "ARGS";
}
else
{
# If arguments exist, then append all with underscore delimeter, else specify <noArgs>
if ($(command_column+1) != "")
{
args = $(command_column+1);
for (i=command_column+2; i<=NF; i++)
{
args = args "_" $i;
$i = "";
}
$(command_column+1) = args;
}
else
{
$(command_column+1) = "<noArgs>";
}
# Remove trailing white spaces if any
sub(/[ \t]+$/,"",$0);
}
print;
}'
# Execute the command
$CMD | tee "$TEE_DEST" | $AWK "$ARGS_FORMAT"
echo "Cmd = [$CMD]; $AWK '$ARGS_FORMAT'" >> "$TEE_DEST"

110
bin/ps_metric.sh Executable file
View file

@ -0,0 +1,110 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# jscpd:ignore-start
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
# shellcheck disable=SC2166
if [ "$KERNEL" = "Linux" -o "$KERNEL" = "Darwin" -o "$KERNEL" = "FreeBSD" ] ; then
assertHaveCommand ps
CMD='ps auxww'
if [ "$KERNEL" = "Linux" ] ; then
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=$(hostname -I | cut -d\ -f1) -v IPv6_Address=$(ip -6 -brief address show scope global | xargs | cut -d ' ' -f 3 | cut -d '/' -f 1)"
else
DEFINE="-v OSName=$(cat /etc/*release | grep '\bNAME=' | cut -d '=' -f2 | tr ' ' '_' | cut -d\" -f2) -v OS_version=$(cat /etc/*release | grep '\bVERSION_ID=' | cut -d '=' -f2 | cut -d\" -f2) -v IP_address=$(hostname -I | cut -d\ -f1) -v IPv6_Address=$(ip -6 -brief address show scope global | xargs | cut -d ' ' -f 3 | cut -d '/' -f 1)"
fi
elif [ "$KERNEL" = "Darwin" -o "$KERNEL" = "FreeBSD" ] ; then
# Filters have been applied to get rid of IPv6 addresses designated for special usage to extract only the global IPv6 address.
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) -v IPv6_Address=$(ifconfig -a | grep inet6 | grep -v ' ::1 ' | grep -v ' ::1/' | grep -v ' ::1%' | grep -v ' fe80::' | grep -v ' 2002::' | grep -v ' ff00::' | head -n 1 | xargs | cut -d '/' -f 1 | cut -d '%' -f 1 | cut -d ' ' -f 2)"
fi
elif [ "$KERNEL" = "AIX" ] ; then
assertHaveCommandGivenPath /usr/sysv/bin/ps
CMD='/usr/sysv/bin/ps -eo user,pid,psr,pcpu,time,pmem,rss,vsz,tty,s,etime,args'
# Filters have been applied to get rid of IPv6 addresses designated for special usage to extract only the global IPv6 address.
DEFINE="-v OSName=$(uname -s) -v OS_version=$(oslevel -r | cut -d'-' -f1) -v IP_address=$(ifconfig -a | grep 'inet ' | grep -v 127.0.0.1 | cut -d\ -f2 | head -n 1) -v IPv6_Address=$(ifconfig -a | grep inet6 | grep -v ' ::1 ' | grep -v ' ::1/' | grep -v ' ::1%' | grep -v ' fe80::' | grep -v ' 2002::' | grep -v ' ff00::' | head -n 1 | xargs | cut -d '/' -f 1 | cut -d '%' -f 1 | cut -d ' ' -f 2)"
elif [ "$KERNEL" = "SunOS" ] ; then
assertHaveCommandGivenPath /usr/bin/ps
CMD='/usr/bin/ps -eo user,pid,psr,pcpu,time,pmem,rss,vsz,tty,s,etime,args'
# Filters have been applied to get rid of IPv6 addresses designated for special usage to extract only the global IPv6 address.
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) -v IPv6_Address=$(ifconfig -a | grep inet6 | grep -v ' ::1 ' | grep -v ' ::1/' | grep -v ' ::1%' | grep -v ' fe80::' | grep -v ' 2002::' | grep -v ' ff00::' | head -n 1 | xargs | cut -d '/' -f 1 | cut -d '%' -f 1 | cut -d ' ' -f 2)"
elif [ "$KERNEL" = "HP-UX" ] ; then
HEADER='USER PID PSR pctCPU CPUTIME pctMEM RSZ_KB VSZ_KB TTY S ELAPSED OSName OS_version IP_address COMMAND ARGS'
# shellcheck disable=SC2016
FORMAT='{sub("^_", "", $1); if (NF>12) {args=$13; for (j=14; j<=NF; j++) args = args "_" $j} else args="<noArgs>"; sub("^[^\134[: -]*/", "", $12);OSName=OSName;OS_version=OS_version;IP_address=IP_address;}'
# shellcheck disable=SC2016
PRINTF='{if (NR == 1) {print $0} else {printf "%-32.32s %8s %4s %6s %12s %6s %8s %8s %-7.7s %1.1s %15s %-35s %15s %-16s %-100.100s %s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, OSName, OS_version, IP_address, $12, args}}'
FILL_DIMENSIONS='{length(IP_address) || IP_address = "?";length(OS_version) || OS_version = "?";length(OSName) || OSName = "?"}'
# shellcheck disable=SC2016
HEADERIZE='{NR == 1 && $0 = header}'
assertHaveCommand ps
export UNIX95=1
CMD='ps -e -o ruser,pid,pset,pcpu,time,vsz,tty,state,etime,args'
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='{sub("^_", "", $1); if (NF>12) {args=$13; for (j=14; j<=NF; j++) args = args "_" $j} else args="<noArgs>"; sub("^[\[\]]", "", $11);OSName=OSName;OS_version=OS_version;IP_address=IP_address;}'
# shellcheck disable=SC2016
PRINTF='if (NR == 1) {print $0} else {printf "%-14.14s %6s %4s %6s %12s %6s %8s %8s %-7.7s %1.1s %12s %-35s %15s %-16s %-18.18s %s\n", $1, $2, $3, $4, $5, "?", "?", $6, $7, $8, $9, $10, OSName, OS_version, IP_address, $11, arg}}'
# shellcheck disable=SC2086
$CMD | tee "$TEE_DEST" | $AWK $DEFINE "$HEADERIZE $FILL_DIMENSIONS $FORMAT $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK $DEFINE '$HEADERIZE $FILL_DIMENSIONS $FORMAT $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"
exit
fi
# shellcheck disable=SC2016
# awk logic for adding extra field ARGS with underscore delimiter and OSName, OS_version, IP_address
FORMAT='BEGIN {OFS = " ";} # specify output field separator
{
if (NR == 1) # Add extra headers/fields - ARGS,OSName,OS_version,IP_address in first (header) row
{
# Replace TIME with CPUTIME to solve field extraction issue (metrics index)
sub("TIME","CPUTIME",$0);
command_column = NF;
$(NF+1) = "ARGS";
$(NF+1) = "OSName";
$(NF+1) = "OS_version";
$(NF+1) = "IP_address";
$(NF+1) = "IPv6_Address";
}
else
{
# If arguments exist, then append all with underscore delimeter, else specify <noArgs>
if ($(command_column+1) != "")
{
args = $(command_column+1);
for (i=command_column+2; i<=NF; i++)
{
args = args "_" $i;
$i = "";
}
$(command_column+1) = args;
}
else
{
$(command_column+1) = "<noArgs>";
}
# Append OSName, OS_version, IP_address values in the last three columns
if (OSName == "") {$(command_column+2) = "?";} else {$(command_column+2) = OSName;}
if (OS_version == "") {$(command_column+3) = "?";} else {$(command_column+3) = OS_version;}
if (IP_address == "") {$(command_column+4) = "?";} else {$(command_column+4) = IP_address;}
if (IPv6_Address == "") {$(command_column+5) = "?";} else {$(command_column+5) = IPv6_Address;}
# Remove trailing white spaces if any
sub(/[ \t]+$/,"",$0);
}
print;
}'
# shellcheck disable=SC2086
# Execute the command
$CMD | tee "$TEE_DEST" | $AWK $DEFINE "$FORMAT"
echo "Cmd = [$CMD]; $AWK $DEFINE '$FORMAT'" >> "$TEE_DEST"
# jscpd:ignore-end

61
bin/rlog.sh Executable file
View file

@ -0,0 +1,61 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
#
# credit for improvement to http://splunk-base.splunk.com/answers/41391/rlogsh-using-too-much-cpu
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
OLD_SEEK_FILE=$SPLUNK_HOME/var/run/splunk/unix_audit_seekfile # For handling upgrade scenarios
CURRENT_AUDIT_FILE=/var/log/audit/audit.log # For handling upgrade scenarios
SEEK_FILE=$SPLUNK_HOME/var/run/splunk/unix_audit_seektime
TMP_ERROR_FILTER_FILE=$SPLUNK_HOME/var/run/splunk/unix_rlog_error_tmpfile # For filering out "no matches" error from stderr
AUDIT_FILE="/var/log/audit/audit.log*"
if [ "$KERNEL" = "Linux" ] ; then
assertHaveCommand service
assertHaveCommandGivenPath /sbin/ausearch
if [ -n "$(service auditd status 2>/dev/null)" ] && [ "$(service auditd status 2>/dev/null)" ] ; then
CURRENT_TIME=$(date --date="1 seconds ago" "+%x %T") # 1 second ago to avoid data loss
if [ -e "$SEEK_FILE" ] ; then
SEEK_TIME=$(head -1 "$SEEK_FILE")
# shellcheck disable=SC2086
awk " { print } " $AUDIT_FILE | /sbin/ausearch -i -ts $SEEK_TIME -te $CURRENT_TIME 2>$TMP_ERROR_FILTER_FILE | grep -v "^----";
# shellcheck disable=SC2086
grep -v "<no matches>" < $TMP_ERROR_FILTER_FILE 1>&2
elif [ -e "$OLD_SEEK_FILE" ] ; then
rm -rf "$OLD_SEEK_FILE" # remove previous checkpoint
# start ingesting from the first entry of current audit file
# shellcheck disable=SC2086
awk ' { print } ' $CURRENT_AUDIT_FILE | /sbin/ausearch -i -te $CURRENT_TIME 2>$TMP_ERROR_FILTER_FILE | grep -v "^----";
# shellcheck disable=SC2086
grep -v "<no matches>" <$TMP_ERROR_FILTER_FILE 1>&2
else
# no checkpoint found
# shellcheck disable=SC2086
awk " { print } " $AUDIT_FILE | /sbin/ausearch -i -te $CURRENT_TIME 2>$TMP_ERROR_FILTER_FILE | grep -v "^----";
# shellcheck disable=SC2086
grep -v "<no matches>" <$TMP_ERROR_FILTER_FILE 1>&2
fi
echo "$CURRENT_TIME" > "$SEEK_FILE" # Checkpoint+
else # Added this condition to get error logs
echo "error occured while running 'service auditd status' command in rlog.sh script. Output : $(service auditd status). Command exited with exit code $?" 1>&2
fi
# remove temporary error redirection file if it exists
# shellcheck disable=SC2086
rm $TMP_ERROR_FILTER_FILE 2>/dev/null
elif [ "$KERNEL" = "SunOS" ] ; then
:
elif [ "$KERNEL" = "Darwin" ] ; then
:
elif [ "$KERNEL" = "HP-UX" ] ; then
:
elif [ "$KERNEL" = "FreeBSD" ] ; then
:
fi

56
bin/selinuxChecker.sh Executable file
View file

@ -0,0 +1,56 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
TMP_ERROR_FILTER_FILE=$SPLUNK_HOME/var/run/splunk/unix_selinux_error_tmpfile # For filtering out awk warning from stderr
PRINTF='END {printf "%s app=selinux %s %s %s %s\n", DATE, FILEHASH, SELINUX, SELINUXTYPE, SETLOCALDEFS}'
if [ "$KERNEL" = "Linux" ] ; then
if [ -f /etc/sysconfig/selinux ] ; then
SELINUX_FILE=/etc/sysconfig/selinux
elif [ -f /etc/selinux/config ] ; then
# shellcheck disable=SC2034
SELINUX_FILE=/etc/selinux/config
else
echo "SELinux not configured." >> "$TEE_DEST"
exit 1
fi
assertHaveCommand cat
# Get file hash
# shellcheck disable=SC2016
CMD='eval date ; eval LD_LIBRARY_PATH=$SPLUNK_HOME/lib $SPLUNK_HOME/bin/openssl sha256 $SELINUX_FILE ; cat $SELINUX_FILE'
# Get the date.
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0}'
# Try to use cross-platform case-insensitive matching for text. Note
# that "match", "tolower", IGNORECASE and other common awk commands or
# options are actually nawk/gawk extensions so avoid them if possible.
# shellcheck disable=SC2016
PARSE_1='/^[Ss][Ee][Ll][Ii][Nn][Uu][Xx]\=/ { SELINUX="selinux=" substr($0,index($0,"=")+1,length($0)) } '
# shellcheck disable=SC2016
PARSE_2='/^[Ss][Ee][Ll][Ii][Nn][Uu][Xx][Tt][Yy][Pp][Ee]\=/ { SELINUXTYPE="selinuxtype=" substr($0,index($0,"=")+1,length($0)) } '
# shellcheck disable=SC2016
PARSE_3='/^[Ss][Ee][Tt][Ll][Oo][Cc][Aa][Ll][Dd][Ee][Ff][Ss]\=/ { SETLOCALDEFS="setlocaldefs=" substr($0,index($0,"=")+1,length($0)) } '
# shellcheck disable=SC2016
PARSE_4='/^SHA256/ {FILEHASH="file_hash=" $2}'
MESSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4"
# shellcheck disable=SC2086
$CMD | tee "$TEE_DEST" | $AWK "$MESSAGE $PRINTF" 2> $TMP_ERROR_FILTER_FILE
# shellcheck disable=SC2086
grep -v "warning: regexp escape sequence" < $TMP_ERROR_FILTER_FILE 1>&2
# shellcheck disable=SC2086
rm $TMP_ERROR_FILTER_FILE 2>/dev/null
echo "Cmd = [$CMD]; | $AWK '$MESSAGE $PRINTF'" >> "$TEE_DEST"
fi

196
bin/service.sh Executable file
View file

@ -0,0 +1,196 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
# In AWK scripts in this file, the following are true:
# FULLTEXT is used to capture the output for SHA256 checksum generation.
# SPLUNKD is used to determine Splunk service status.
if [ "$KERNEL" = "Linux" ] ; then
if ! queryHaveCommand systemctl; then
assertHaveCommand date
assertHaveCommand chkconfig
CMD='eval date ; /sbin/chkconfig --list'
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0 ; FULLTEXT=""}'
# shellcheck disable=SC2016
PARSE_1='NR>1 {
FULLTEXT = FULLTEXT $0 "\n"
split($0, ARR)
EVT="app=" ARR[1]
for (i=0 ; i<7 ; i++) {
split(ARR[i+2], STATE, ":")
EVT = EVT " runlevel" i "=" STATE[2]
}
if (ARR[1] ~ /[Ss][Pp][Ll][Uu][Nn][Kk]/) { SPLUNKD=1 }
printf "%s type=chkconfig %s\n", DATE, EVT
}'
MASSAGE="$PARSE_0 $PARSE_1"
# Send the collected full text to openssl; this avoids any timing discrepancies
# between when the information is collected and when we process it.
# shellcheck disable=SC2016
POSTPROCESS='END {
if (SPLUNKD==0) { printf "%s app=\"Splunk\" StartMode=Disabled\n", DATE }
printf "%s %s", DATE, "file_hash="
printf "%s", FULLTEXT | "LD_LIBRARY_PATH=$SPLUNK_HOME/lib $SPLUNK_HOME/bin/openssl sha256"
}'
else
assertHaveCommand systemctl
assertHaveCommand date
# Run the systemctl command to get all units and their state
CMD='eval date; systemctl list-units --type=service --all'
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0}'
# shellcheck disable=SC2016
PARSE_1='
# On header row, get lengths to the fields
NR==2 {
match($0, /^ */); leading=RLENGTH;
match($0, /^.*DESC/); desclen=RLENGTH-4;
FULLTEXT="";
next;
}'
# shellcheck disable=SC2016
PARSE_2='(NR > 2){
# Stop at the empty line
if ( !NF ) { exit; }
# Skip the leading spaces
$0 = substr( $0, leading );
# the description spans fields so catch it seperately
desc=substr( $0, desclen );
FULLTEXT = FULLTEXT $0 "\n"
if ($1 ~ /[Ss][Pp][Ll][Uu][Nn][Kk]/) { SPLUNKD=1 }
printf "%s type=systemctl UNIT=%s, LOADED=%s, ACTIVE=%s, SUB=%s, DESCRIPTION=\"%s\" \n",DATE, $1, $2, $3, $4, desc
}'
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_2"
# shellcheck disable=SC2016
POSTPROCESS='END {
if (SPLUNKD==0) { printf "%s app=\"Splunk\" StartMode=Disabled\n", DATE }
printf "%s %s", DATE, "file_hash="
printf "%s", FULLTEXT | "LD_LIBRARY_PATH=$SPLUNK_HOME/lib $SPLUNK_HOME/bin/openssl sha256"
}'
fi
elif [ "$KERNEL" = "SunOS" ] ; then
assertHaveCommand date
assertHaveCommand svcs
CMD='eval date ; svcs -H -a -o STATE,FMRI'
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0 ; FULLTEXT=""}'
# shellcheck disable=SC2016
PARSE_1='NR>1 {
STATE="State=\""$1"\""
idx=index($2,":")
STARTNAME="StartName=\""substr($2,0,idx-1)"\""
APP="app=\""substr($2,idx+1)"\""
FULLTEXT=FULLTEXT $0 "\n"
}'
PARSE_2='/^legacy_run/ {
STARTMODE="StartMode=\"Auto\""
}'
PARSE_3='/^online/ {
STARTMODE="StartMode=\"Auto\""
STATE="State=\"Running\""
}'
PARSE_4='/^disabled/ {
STARTMODE="StartMode=\"Disabled\""
STATE="State=\"Stopped\""
}'
INLINE_PRINT='NR>1 && APP!=0 {printf "%s %s %s %s %s\n", DATE, APP, STARTMODE, STARTNAME, STATE}'
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $INLINE_PRINT"
# Send the collected full text to openssl; this avoids any timing discrepancies
# between when the information is collected and when we process it.
# shellcheck disable=SC2016
POSTPROCESS='END {
if (SPLUNKD==0) { printf "%s app=\"Splunk\" StartMode=Disabled\n", DATE }
printf "%s %s", DATE, "file_hash="
printf "%s", FULLTEXT | "LD_LIBRARY_PATH=$SPLUNK_HOME/lib $SPLUNK_HOME/bin/openssl sha256"
}'
elif [ "$KERNEL" = "Darwin" ] ; then
assertHaveCommand date
assertHaveCommand defaults
assertHaveCommand dscl
assertHaveCommand find
assertHaveCommand ls
# Get startup items
CMD='eval date ; ls -1 /System/Library/StartupItems/ /Library/StartupItems/'
# Get per-user startup items
# shellcheck disable=SC2044
for PLIST_FILE in $(find /Users -name "loginwindow.plist") ; do
CMD=$CMD' ; echo '$PLIST_FILE': ; defaults read '$PLIST_FILE
done
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0}'
# Retrieve path for system startup items
# shellcheck disable=SC2016
PARSE_1='/^\/(System|Library)/ {
split($0, tmparr, ":")
PATH="file_path=\""tmparr[1]
USER=0
START_MODE="StartMode=Auto"
START_TYPE="StartType=startup"
}'
# Retrieve user information for user startup items.
# shellcheck disable=SC2016
PARSE_2='/^\/Users/ {
split($0, tmparr, "/")
USER="user=" tmparr[3]
START_MODE="StartMode=Auto"
START_TYPE="StartType=login"
}'
# Retrieve the path for user startup items.
# shellcheck disable=SC2016
PARSE_3='/[[:blank:]]*Path/ {
split($0, path_arr, "=")
num=split(path_arr[2], app_arr, "/")
split(app_arr[num], app_final, ".")
split(path_arr[2], path_final, "\"")
APP="app=\"" app_final[1] "\""
FILE_PATH="file_path=\"" path_final[2] "\""
# Only print if we find a path.
printf "%s %s %s %s %s %s\n", DATE, APP, START_MODE, START_TYPE, FILE_PATH, USER
# Note that we found splunkd if app matches
if (APP ~ /[Ss][Pp][Ll][Uu][Nn][Kk]/) { SPLUNKD=1 }
}'
# Retrieve the system startup item name from the output of "ls -1"
# shellcheck disable=SC2016
PARSE_4='/^[^\/]/ {
if (NR>1 && USER==0 && NF > 0) {
APP="app=\""$0"\""
PATH=PATH$0"\""
printf "%s %s %s %s %s\n", DATE, APP, START_MODE, START_TYPE, PATH
}
# Note that we found splunkd if app matches
if (APP ~ /[Ss][Pp][Ll][Uu][Nn][Kk]/) { SPLUNKD=1 }
}'
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4"
POSTPROCESS='END { if (SPLUNKD==0) { printf "%s app=\"Splunk\" StartMode=Disabled\n", DATE } }'
else
# Exits
failUnsupportedScript
fi
$CMD | tee "$TEE_DEST" | $AWK "$MASSAGE $POSTPROCESS"
echo "Cmd = [$CMD]; | $AWK '$MASSAGE $POSTPROCESS'" >> "$TEE_DEST"

1276
bin/setup.sh Executable file

File diff suppressed because it is too large Load diff

38
bin/setupservice.py Normal file
View file

@ -0,0 +1,38 @@
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
import json
import sys
import splunk
import splunk.bundle as bundle
class SetupService(splunk.rest.BaseRestHandler):
def handle_GET(self):
try:
is_recognized_unix = not sys.platform.startswith("win")
self.response.write(json.dumps(is_recognized_unix))
except Exception as e:
self.response.write(e)
def handle_POST(self):
sessionKey = self.sessionKey
try:
conf = bundle.getConf(
"app", sessionKey, namespace="Splunk_TA_nix", owner="nobody"
)
stanza = conf.stanzas["install"].findKeys("is_configured")
if stanza:
if stanza["is_configured"] == "0" or stanza["is_configured"] == "false":
conf["install"]["is_configured"] = "true"
splunk.rest.simpleRequest(
"/apps/local/Splunk_TA_nix/_reload", sessionKey=sessionKey
)
else:
conf["install"]["is_configured"] = "true"
splunk.rest.simpleRequest(
"/apps/local/Splunk_TA_nix/_reload", sessionKey=sessionKey
)
except Exception as e:
self.response.write(e)

98
bin/sshdChecker.sh Executable file
View file

@ -0,0 +1,98 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
SSH_CONFIG_FILE=""
if [ "$KERNEL" = "Linux" ] || [ "$KERNEL" = "SunOS" ] ; then
SSH_CONFIG_FILE=/etc/ssh/sshd_config
elif [ "$KERNEL" = "Darwin" ] ; then
SSH_CONFIG_FILE=/etc/sshd_config
else
failUnsupportedScript
fi
FILL_BLANKS='END {
if (SSHD_PROTOCOL == 0) {
SSHD_PROTOCOL=SSHD_DEFAULT_PROTOCOL
}'
PRINTF='{printf "%s app=sshd %s %s\n", DATE, FILEHASH, SSHD_PROTOCOL}}'
if [ "x$SOLARIS_11" != "xtrue" ] ; then
# If $SSH_CONFIG_FILE file exists and is a regular file.
if [ -f "$SSH_CONFIG_FILE" ] ; then
assertHaveCommand cat
# Get file hash
# shellcheck disable=SC2016
CMD='eval date ; eval LD_LIBRARY_PATH=$SPLUNK_HOME/lib $SPLUNK_HOME/bin/openssl sha256 $SSH_CONFIG_FILE ; cat $SSH_CONFIG_FILE'
# Get the date.
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0}'
# Try to use cross-platform case-insensitive matching for text. Note
# that "match", "tolower", IGNORECASE and other common awk commands or
# options are actually nawk/gawk extensions so avoid them if possible.
# shellcheck disable=SC2016
PARSE_1='/^[Pp][Rr][Oo][Tt][Oo][Cc][Oo][Ll]/ {
split($0, arr)
num = split(arr[2], protocols, ",")
if (num == 2) {
SSHD_PROTOCOL="sshd_protocol=" protocols[1] "/" protocols[2]
} else {
SSHD_PROTOCOL="sshd_protocol=" protocols[1]
}
}'
# shellcheck disable=SC2016
PARSE_2='/^#[[:blank:]]*[Pp][Rr][Oo][Tt][Oo][Cc][Oo][Ll]/ {
num=split($0, arr)
protonum = split(arr[num], protocols, ",")
if (protonum == 2) {
SSHD_DEFAULT_PROTOCOL="sshd_protocol=" protocols[1] "/" protocols[2]
} else {
SSHD_DEFAULT_PROTOCOL="sshd_protocol=" protocols[1]
}
}'
# shellcheck disable=SC2016
PARSE_3='/^SHA256/ {FILEHASH="file_hash=" $2}'
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3"
else
# shellcheck disable=SC2016
echo "SSHD configuration (file: $SSH_CONFIG_FILE) missing or unreadable." >> "$TEE_DEST"
exit 1
fi
else
if [ -f "$SSH_CONFIG_FILE" ] && [ -r "$SSH_CONFIG_FILE" ] ; then
# Solaris 11 only supports SSH protocol 2.
assertHaveCommand cat
# Get file hash
# shellcheck disable=SC2016
CMD='eval date ; eval LD_LIBRARY_PATH=$SPLUNK_HOME/lib $SPLUNK_HOME/bin/openssl sha256 $SSH_CONFIG_FILE'
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0 ; SSHD_PROTOCOL="sshd_protocol=2"}'
# shellcheck disable=SC2016
PARSE_1='/^SHA256/ {FILEHASH="file_hash=" $2}'
MASSAGE="$PARSE_0 $PARSE_1"
else
echo "SSHD configuration (file: $SSH_CONFIG_FILE) missing or unreadable." >> "$TEE_DEST"
exit 1
fi
fi
$CMD | tee "$TEE_DEST" | $AWK "$MASSAGE $FILL_BLANKS $PRINTF"
echo "Cmd = [$CMD]; | $AWK '$MASSAGE $FILL_BLANKS $PRINTF'" >> "$TEE_DEST"

67
bin/time.sh Executable file
View file

@ -0,0 +1,67 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
queryHaveCommand ntpdate
FOUND_NTPDATE=$?
queryHaveCommand sntp
FOUND_SNTP=$?
getServer ()
{
if [ -f /etc/ntp.conf ] ; then # Linux; FreeBSD; AIX; Mac OS X maybe
CONFIG=/etc/ntp.conf
elif [ -f /etc/inet/ntp.conf ] ; then # Solaris
CONFIG=/etc/inet/ntp.conf
elif [ -f /private/etc/ntp.conf ] ; then # Mac OS X
CONFIG=/private/etc/ntp.conf
else
CONFIG=
fi
SERVER_DEFAULT='0.pool.ntp.org'
if [ "$CONFIG" = "" ] ; then
SERVER=$SERVER_DEFAULT
else
# shellcheck disable=SC2016
SERVER=$($AWK '/^server / {print $2; exit}' "$CONFIG")
SERVER=${SERVER:-$SERVER_DEFAULT}
fi
}
#With ntpdate
if [ $FOUND_NTPDATE -eq 0 ] ; then
echo "Found ntpdate command" >> "$TEE_DEST"
getServer
CMD2="ntpdate -q $SERVER"
echo "CONFIG=$CONFIG, SERVER=$SERVER" >> "$TEE_DEST"
#With sntp
elif [ "$KERNEL" = "Darwin" ] && [ $FOUND_SNTP -eq 0 ] ; then # Mac OS 10.14.6 or higher version
echo "Found sntp command" >> "$TEE_DEST"
getServer
CMD2="sntp $SERVER"
echo "CONFIG=$CONFIG, SERVER=$SERVER" >> "$TEE_DEST"
#With Chrony
else
CMD2="chronyc -n sources"
fi
CMD1='date'
assertHaveCommand $CMD1
assertHaveCommand "$CMD2"
$CMD1 | tee -a "$TEE_DEST"
echo "Cmd1 = [$CMD1]" >> "$TEE_DEST"
$CMD2 | tee -a "$TEE_DEST"
echo "Cmd2 = [$CMD2]" >> "$TEE_DEST"

87
bin/top.sh Executable file
View file

@ -0,0 +1,87 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER=' PID USER PR NI VIRT RES SHR S pctCPU pctMEM cpuTIME COMMAND'
# shellcheck disable=SC2016
PRINTF='{printf "%6s %-14s %4s %4s %6s %6s %6s %2s %6s %6s %12s %-s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12}'
CMD='top'
if [ "$KERNEL" = "Linux" ] ; then
CMD='top -bn 1'
FILTER='{if (NR < 7) next}'
# shellcheck disable=SC2016
HEADERIZE='{NR == 7 && $0 = header}'
elif [ "$KERNEL" = "SunOS" ] ; then
CMD='prstat -n 999 1 1'
HEADERIZE="BEGIN {print \"$HEADER\"}"
FILTER='(NR==1) {next} /^Total:|^$/ {exit}'
# shellcheck disable=SC2016
FORMAT_DOMAIN='{virt=$3; res=$4; stateRaw=$5; pr=$6; ni=$7; cpuTIME=$8; pctCPU=0.0+$9; sub("/.*$", "", $10); command=$10 ? $10 : "<n/a>"}'
SPECIFY_STATES_MAP='BEGIN {map["sleep"]="S"; map["stop"]="T"; map["zombie"]="Z"; map["wait"]="D"; map["cpu"]="R"}'
MAP_STATE='{sub("[0-9]+$", "", stateRaw); state=map[stateRaw]}'
# shellcheck disable=SC2016
FORMAT_RANGE='{$3=pr; $4=ni; $5=virt; $6=res; $7="?"; $8=state; $9=pctCPU; $10="?"; $11=cpuTIME; $12=command}'
FORMAT="$FORMAT_DOMAIN $SPECIFY_STATES_MAP $MAP_STATE $FORMAT_RANGE"
elif [ "$KERNEL" = "AIX" ] ; then
CMD="eval /usr/sysv/bin/ps -eo pid,user,pri,nice,vsz,rss,s,s,pcpu,pmem,time,comm"
HEADERIZE="BEGIN {print \"$HEADER\"}"
FILTER='/PID/{next}'
# shellcheck disable=SC2016
FORMAT='{$7="?" ; sub("A","R",$8)}'
# Substitute ? for temporary [field 7] &
# Substitute R(running) for A(Active) on field 8 in AIX by Jacky Ho, Systex
elif [ "$KERNEL" = "Darwin" ] ; then
if [ "$OSX_MAJOR_VERSION" = 10 ] && [ "$OSX_MINOR_VERSION" -ge 9 ] || [ "$OSX_MAJOR_VERSION" -ge 11 ]; then
# OS X 10.9 does not report rshrd statistic (Resident Shared Address Space Size)
CMD="eval top -F -l 2 -ocpu -Otime -stats pid,username,vsize,rsize,cpu,time,command"
# shellcheck disable=SC2016
FORMAT='{gsub("[+-] ", " "); virt=$3; res=$4; shr="?"; pctCPU=$5; cpuTIME=$6; command=$7; $3="?"; $4="?"; $5=virt; $6=res; $7=shr; $8="?"; $9=pctCPU; $10="?"; $11=cpuTIME; $12=command}'
elif $OSX_GE_SNOW_LEOPARD; then
CMD="eval top -F -l 2 -ocpu -Otime -stats pid,username,vsize,rsize,rshrd,cpu,time,command"
# shellcheck disable=SC2016
FORMAT='{gsub("[+-] ", " "); virt=$3; res=$4; shr=$5; pctCPU=$6; cpuTIME=$7; command=$8; $3="?"; $4="?"; $5=virt; $6=res; $7=shr; $8="?"; $9=pctCPU; $10="?"; $11=cpuTIME; $12=command}'
else
CMD="eval top -F -l 2 -ocpu -Otime -t -R -p '^aaaaa ^nnnnnnnnnnnnnnnnnn ^lllll ^jjjjj ^ccccc ^ddddd ^bbbbbbbbbbbbbbbbbbbbbbbbbbbbb'"
# shellcheck disable=SC2016
FORMAT='{ virt=$3; res=$4; pctCPU=$5; cpuTIME=$6; command=$7; $3="?"; $4="?"; $5=virt; $6=res; $7="?"; $8="?"; $9=pctCPU; $10="?"; $11=cpuTIME; $12=command}'
fi
HEADERIZE="BEGIN {print \"$HEADER\"}"
FILTER='/ %CPU / {reportOrd++; next} {if ((reportOrd < 2) || !length) next}'
elif [ "$KERNEL" = "HP-UX" ] ; then
assertHaveCommand ps
HEADERIZE="BEGIN {print \"$HEADER\"}"
FILTER='/PID/{next}'
export UNIX95=1
CMD='ps -e -o pid,user,pri,nice,vsz,state,pcpu,time,comm'
# shellcheck disable=SC2016
PRINTF='{q="?"; printf "%6s %-14s %4s %4s %6s %6s %6s %2s %6s %6s %12s %-s\n", $1, $2, $3, $4, $5, q, q, $6, $7, q, $8, $9}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
line=$(top -Sb 999 | grep -n -m 1 "PID" | cut -f1 -d:)
CMD='top -Sb 999'
HEADERIZE="BEGIN {print \"$HEADER\"}"
FILTER='(NR<='$line') {next} /^$/ {next}'
# shellcheck disable=SC2016
FORMAT_DOMAIN='{pr=$4; ni=$5; virt=$6; res=$7; stateRaw=$8; cpuTIME=$10; pctCPU=0+$11; command=$12}'
SPECIFY_STATES_MAP='BEGIN {map["SLEEP"]="S"; map["STOP"]="T"; map["ZOMB"]="Z"; map["WAIT"]="D"; map["LOCK"]="D"; map["START"]="R"; map["RUN"]="R"; map["CPU"]="R"}'
MAP_STATE='{sub("[0-9]+$", "", stateRaw); state=map[stateRaw]; state=state ? state : "?"}'
# shellcheck disable=SC2016
FORMAT_RANGE='{$3=pr; $4=ni; $5=virt; $6=res; $7="?"; $8=state; $9=pctCPU; $10="?"; $11=cpuTIME; $12=command}'
FORMAT="$FORMAT_DOMAIN $SPECIFY_STATES_MAP $MAP_STATE $FORMAT_RANGE"
fi
# shellcheck disable=SC2086
assertHaveCommand $CMD
out=$($CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $FILTER $FORMAT $PRINTF" header="$HEADER")
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 1 ]; then
echo "$out"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $FILTER $FORMAT $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"
else
echo "No data is present" >> "$TEE_DEST"
fi

130
bin/update.sh Executable file
View file

@ -0,0 +1,130 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
TMP_ERROR_FILTER_FILE=$SPLUNK_HOME/var/run/splunk/unix_update_error_tmpfile # For filering out apt warning from stderr
if [ "$KERNEL" = "Linux" ] ; then
assertHaveCommand date
OSName=$(cat /etc/*release | grep '\bNAME=' | cut -d '=' -f2 | tr ' ' '_' | cut -d\" -f2)
OS_FILE=/etc/os-release
# Ubuntu doesn't have yum installed by default hence apt is being used to get the list of upgradable packages
if [ "$OSName" = "Ubuntu" ]; then
assertHaveCommand apt
assertHaveCommand sed
# sed command here replaces '/, [, ]' with ' '
CMD='eval date ; eval apt list --upgradable | sed "s/\// /; s/\[/ /; s/\]/ /"'
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0}'
# shellcheck disable=SC2016
PARSE_1='NR>2 { printf "%s package=%s ubuntu_update_stream=%s latest_package_version=%s ubuntu_architecture=%s current_package_version=%s\n", DATE, $1, $2, $3, $4, $7}'
MESSAGE="$PARSE_0 $PARSE_1"
elif echo "$OS_ID" | grep -qi suse; then
assertHaveCommand zypper
# shellcheck disable=SC2016
CMD='eval date ; zypper list-updates'
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0}'
# shellcheck disable=SC2016
PARSE_1='/^[\-+]+/ {header_found = 1; next}'
# shellcheck disable=SC2016
PARSE_2='header_found { gsub(/[[:space:]]*\|[[:space:]]*/, "|"); split($0, arr, /\|/); printf "%s repository=%s package=%s current_package_version=%s latest_package_version=%s sles_architecture=%s\n", DATE, arr[2], arr[3], arr[4], arr[5], arr[6]}'
MESSAGE="$PARSE_0 $PARSE_1 $PARSE_2"
else
assertHaveCommand yum
CMD='eval date ; yum check-update'
# shellcheck disable=SC2016
PARSE_0='NR==1 {
DATE=$0
PROCESS=0
UPDATES["addons"]=0
UPDATES["base"]=0
UPDATES["extras"]=0
UPDATES["updates"]=0
}'
# Skip extraneous text up to first blank line.
# shellcheck disable=SC2016
PARSE_1='NR>1 && PROCESS==0 && $0 ~ /^[[:blank:]]*$|^$/ {
PROCESS=1
}'
# shellcheck disable=SC2016
PARSE_2='NR>1 && PROCESS==1 {
num = split($0, update_array)
if (num == 3) {
# Record the update count
UPDATES[update_array[3]] = UPDATES[update_array[3]]+1
printf "%s package=\"%s\" package_type=\"%s\"\n", DATE, update_array[1], update_array[3]
} else if (num==2 && update_array[1] != "") {
printf "%s package=\"%s\"\n", DATE, update_array[1]
}
}'
PARSE_3='END {
TOTALS=""
for (key in UPDATES) {
TOTALS=TOTALS key "=" UPDATES[key] " "
}
printf "%s %s\n", DATE, TOTALS
}'
MESSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3"
fi
elif [ "$KERNEL" = "Darwin" ] ; then
assertHaveCommand date
assertHaveCommand softwareupdate
CMD='eval date ; softwareupdate -l'
# shellcheck disable=SC2016
PARSE_0='NR==1 {
DATE=$0
PROCESS=0
TOTAL=0
}'
# If the first non-space character is an asterisk, assume this is the name
# of the update. Otherwise, print the update.
# shellcheck disable=SC2016
PARSE_1='NR>1 && PROCESS==1 && $0 !~ /^[[:blank:]]*$/ {
if ( $0 ~ /^[[:blank:]]*\*/ ) {
PACKAGE="package=\"" $2 "\""
RECOMMENDED=""
RESTART=""
TOTAL=TOTAL+1
} else {
if ( $0 ~ /recommended/ ) { RECOMMENDED="is_recommended=\"true\"" }
if ( $0 ~ /restart/ ) { RESTART="restart_required=\"true\"" }
printf "%s %s %s %s\n", DATE, PACKAGE, RECOMMENDED, RESTART
}
}'
# Use sentinel value to skip all text prior to update list.
# shellcheck disable=SC2016
PARSE_2='NR>1 && PROCESS==0 && $0 ~ /found[[:blank:]]the[[:blank:]]following/ {
PROCESS=1
}'
PARSE_3='END {
printf "%s total_updates=%s\n", DATE, TOTAL
}'
MESSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3"
else
# Exits
failUnsupportedScript
fi
# shellcheck disable=SC2086
$CMD 2> $TMP_ERROR_FILTER_FILE | tee "$TEE_DEST" | $AWK "$MESSAGE"
# shellcheck disable=SC2086
grep -Ev "apt does not have a stable CLI interface|^[[:space:]]*$" < $TMP_ERROR_FILTER_FILE 1>&2
# shellcheck disable=SC2086
rm $TMP_ERROR_FILTER_FILE 2>/dev/null
echo "Cmd = [$CMD]; | $AWK '$MESSAGE'" >> "$TEE_DEST"

52
bin/uptime.sh Executable file
View file

@ -0,0 +1,52 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
PRINTF='END {printf "%s SystemUpTime=%s\n", DATE, UPTIME}'
# On HP-UX the `ps` command will only recognize the `-o` option if
# the `UNIX95` environment variable is set. So do it.
#
# Careful: The `UNIX95` environment variable affects other common
# commands like `cp`.
if [ "$KERNEL" = "HP-UX" ]; then
export UNIX95=1
fi
# This should work for any POSIX-compliant system, but in case it doesn't
# we have left the individual OS names here to be broken out later on.
if [ "$KERNEL" = "Linux" ] || [ "$KERNEL" = "SunOS" ] || [ "$KERNEL" = "AIX" ] || [ "$KERNEL" = "HP-UX" ] || [ "$KERNEL" = "Darwin" ] || [ "$KERNEL" = "FreeBSD" ] ; then
assertHaveCommand date
assertHaveCommand ps
CMD='eval date; LC_ALL=POSIX ps -o etime= -p 1'
# Get the date.
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0}'
# Parse timestamp using only POSIX AWK functions. The match, do/while,
# and exponentiation commands may not be available on some systems.
# shellcheck disable=SC2016
PARSE_1='NR==2 {
if (index($1,"-") != 0) {
split($1, array, "-")
UPTIME=86400*array[1]
num=split(array[2], TIME, ":")
} else {
UPTIME=0
num=split($1, TIME, ":")
}
for (i=num; i>0; i--) {
SECS=TIME[i]
for (j=num-i; j>0; j--) {
SECS = SECS * 60
}
UPTIME = UPTIME + SECS
}
}'
MASSAGE="$PARSE_0 $PARSE_1"
fi
$CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $MASSAGE $FILL_BLANKS $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $MASSAGE $FILL_BLANKS $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"

45
bin/usersWithLoginPrivs.sh Executable file
View file

@ -0,0 +1,45 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
HEADER='USERNAME\tUID\tGID\tHOME_DIR\tUSER_INFO'
HEADERIZE="BEGIN {print \"$HEADER\"}"
CMD='cat /etc/passwd'
AWK_IFS='-F:'
# shellcheck disable=SC2016
FILTER='($NF !~ /sh$/) {next}'
# shellcheck disable=SC2016
PRINTF='{printf "%s\t%s\t%s\t%s\t%s\n", $1, $3, $4, $6, $5}'
if [ "$KERNEL" = "Linux" ] ; then
# shellcheck disable=SC2016
FILL_BLANKS='{$5 || $5 = "?"; length($4) || $4 = "?"; length($3) || $3 = "?"}'
elif [ "$KERNEL" = "SunOS" ] ; then
# shellcheck disable=SC2016
FILL_BLANKS='{$5 || $5 = "?"; length($4) || $4 = "?"; length($3) || $3 = "?"}'
elif [ "$KERNEL" = "AIX" ] ; then
# shellcheck disable=SC2016
FILL_BLANKS='{$5 || $5 = "?"; length($4) || $4 = "?"; length($3) || $3 = "?"}'
elif [ "$KERNEL" = "HP-UX" ] ; then
# shellcheck disable=SC2016
FILL_BLANKS='{$5 || $5 = "?"; length($4) || $4 = "?"; length($3) || $3 = "?"}'
elif [ "$KERNEL" = "Darwin" ] ; then
CMD='dscacheutil -q user'
AWK_IFS=''
# shellcheck disable=SC2016
MASSAGE='/^name: / {username = $2} /^uid: / {UID = $2} /^gid: / {GID = $2} /^dir: / {homeDir = $2} /^shell: / {shell = $2} /^gecos: / {userInfo = $2; for (i=3; i<=NF; i++) userInfo = userInfo " " $i} !/^gecos: / {next}'
FILTER='{if (shell !~ /sh$/) next; if (homeDir ~ /^[0-9]+$/) next}'
PRINTF='{printf "%s\t%s\t%s\t%s\t%s\n", username, length(UID) ? UID : "?", length(GID) ? GID : "?", length(homeDir) ? homeDir : "?", userInfo}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
# shellcheck disable=SC2016
FILL_BLANKS='{$5 || $5 = "?"; length($4) || $4 = "?"; length($3) || $3 = "?"}'
fi
assertHaveCommand "$CMD"
# shellcheck disable=SC2086
$CMD | tee "$TEE_DEST" | $AWK $AWK_IFS "$HEADERIZE $MASSAGE $FILTER $FILL_BLANKS $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK $AWK_IFS '$HEADERIZE $MASSAGE $FILTER $FILL_BLANKS $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"

44
bin/version.sh Executable file
View file

@ -0,0 +1,44 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
PRINTF='END {printf "%s %s %s %s %s %s\n", DATE, MACH_HW_NAME, MACH_ARCH_NAME, OS_REL, OS_NAME, OS_VER}'
if [ "$KERNEL" = "Linux" ] || [ "$KERNEL" = "SunOS" ] || [ "$KERNEL" = "Darwin" ] || [ "$KERNEL" = "FreeBSD" ] ; then
assertHaveCommand date
assertHaveCommand uname
CMD='eval date ; eval uname -m ; eval uname -r ; eval uname -s ; eval uname -v ; eval uname -p'
elif [ "$KERNEL" = "HP-UX" ] ; then
# HP-UX lacks -p switch.
assertHaveCommand date
assertHaveCommand uname
CMD='eval date ; eval uname -m ; eval uname -r ; eval uname -s ; eval uname -v'
elif [ "$KERNEL" = "AIX" ] ; then
# AIX uses oslevel for version and release switch.
assertHaveCommand date
assertHaveCommand uname
CMD='eval date ; eval uname -m ; eval oslevel -r ; eval uname -s ; eval oslevel -s'
fi
# Get the date.
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0}'
# shellcheck disable=SC2016
PARSE_1='NR==2 {MACH_HW_NAME="machine_hardware_name=\"" $0 "\""}'
# shellcheck disable=SC2016
PARSE_2='NR==3 {OS_REL="os_release=\"" $0 "\""}'
# shellcheck disable=SC2016
PARSE_3='NR==4 {OS_NAME="os_name=\"" $0 "\""}'
# shellcheck disable=SC2016
PARSE_4='NR==5 {OS_VER="os_version=\"" $0 "\""}'
# shellcheck disable=SC2016
PARSE_5='NR==6 {MACH_ARCH_NAME="machine_architecture_name=\"" $0 "\""}'
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5"
$CMD | tee "$TEE_DEST" | $AWK "$MASSAGE $PRINTF"
echo "Cmd = [$CMD]; | $AWK '$MASSAGE $PRINTF'" >> "$TEE_DEST"

181
bin/vmstat.sh Executable file
View file

@ -0,0 +1,181 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
# hardware.sh is called in all commands to get CPU counts. The CPU count is required to determine
# the number of threads that waited for execution time. CPU count accounts for hyperthreaded cores so
# (load average - CPU count) gives a reasonable estimate of how many threads were waiting to execute.
HEADER='memTotalMB memFreeMB memUsedMB memFreePct memUsedPct pgPageOut swapUsedPct pgSwapOut cSwitches interrupts forks processes threads loadAvg1mi waitThreads interrupts_PS pgPageIn_PS pgPageOut_PS'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='END {printf "%10d %10d %10d %10.1f %10.1f %10s %10.1f %10s %10s %10s %10s %10s %10s %10.2f %10.2f %10.2f %10.2f %10.2f\n", memTotalMB, memFreeMB, memUsedMB, memFreePct, memUsedPct, pgPageOut, swapUsedPct, pgSwapOut, cSwitches, interrupts, forks, processes, threads, loadAvg1mi, waitThreads, interrupts_PS, pgPageIn_PS, pgPageOut_PS}'
DERIVE='END {memUsedMB=memTotalMB-memFreeMB; memUsedPct=(100.0*memUsedMB)/memTotalMB; memFreePct=100.0-memUsedPct; swapUsedPct=swapUsed ? (100.0*swapUsed)/(swapUsed+swapFree) : 0; waitThreads=loadAvg1mi > cpuCount ? loadAvg1mi-cpuCount : 0}'
if [ "$KERNEL" = "Linux" ] ; then
assertHaveCommand uptime
assertHaveCommand ps
assertHaveCommand vmstat
assertHaveCommand sar
# shellcheck disable=SC2016
CMD='eval uptime ; ps -e | wc -l ; ps -eT | wc -l ; vmstat -s ; `dirname $0`/hardware.sh; sar -B 1 2; sar -I SUM 1 2'
# shellcheck disable=SC2016
PARSE_0='NR==1 {loadAvg1mi=0+$(NF-2)} NR==2 {processes=$1} NR==3 {threads=$1}'
# shellcheck disable=SC2016
PARSE_1='/total memory$/ {memTotalMB=$1/1024} /free memory$/ {memFreeMB+=$1/1024} /buffer memory$/ {memFreeMB+=$1/1024} /swap cache$/ {memFreeMB+=$1/1024}'
# shellcheck disable=SC2016
PARSE_2='/pages paged out$/ {pgPageOut=$1} /used swap$/ {swapUsed=$1} /free swap$/ {swapFree=$1} /pages swapped out$/ {pgSwapOut=$1}'
# shellcheck disable=SC2016
PARSE_3='/interrupts$/ {interrupts=$1} /CPU context switches$/ {cSwitches=$1} /forks$/ {forks=$1}'
# shellcheck disable=SC2016
PARSE_4='/^CPU_COUNT/ {cpuCount=$2}'
# shellcheck disable=SC2016
PARSE_5='($3 ~ "INTR") {nr[NR+3]} NR in nr {interrupts_PS=$3}'
# shellcheck disable=SC2016
PARSE_6='($3 ~ "pgpgin*") {nr2[NR+3]} NR in nr2 {pgPageIn_PS=$2; pgPageOut_PS=$3}'
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $PARSE_6 $DERIVE"
elif [ "$KERNEL" = "SunOS" ] ; then
assertHaveCommand vmstat
assertHaveCommandGivenPath /usr/sbin/swap
assertHaveCommandGivenPath /usr/sbin/prtconf
assertHaveCommand prstat
assertHaveCommand sar
if [ "$SOLARIS_8" = "true" ] || [ "$SOLARIS_9" = "true" ] ; then
# shellcheck disable=SC2016
CMD='eval /usr/sbin/prtconf 2>/dev/null | grep Memory ; /usr/sbin/swap -s ; vmstat 1 2 | sed "3d" ; vmstat -s ; prstat -n 1 1 1; `dirname $0`/hardware.sh; sar -gp 1 2; '
else
# shellcheck disable=SC2016
CMD='eval /usr/sbin/prtconf 2>/dev/null | grep Memory ; /usr/sbin/swap -s ; vmstat -q 1 2 | sed "3d" ; vmstat -s ; prstat -n 1 1 1; `dirname $0`/hardware.sh; sar -gp 1 2'
fi
# shellcheck disable=SC2016
PARSE_0='/^Memory size:/ {memTotalMB=$3} (NR==5) {memFreeMB=$5 / 1024}'
# shellcheck disable=SC2016
PARSE_1='(NR==2) {swapUsed=0+$(NF-3); swapFree=0+$(NF-1)}'
# shellcheck disable=SC2016
PARSE_2='/pages paged out$/ {pgPageOut=$1} /pages swapped out$/ {pgSwapOut=$1}'
# shellcheck disable=SC2016
PARSE_3='/cpu context switches$/ {cSwitches=$1} /device interrupts$/ {interrupts=$1} / v?forks$/ {forks+=$1}'
# shellcheck disable=SC2016
PARSE_4='/^Total: / {processes=$2; threads=$4; loadAvg1mi=0+$(NF-2)}'
# shellcheck disable=SC2016
PARSE_5='/^CPU_COUNT/ {cpuCount=$2}'
# Sample output: http://opensolarisforum.org/man/man1/sar.html
if [ "$SOLARIS_10" = "true" ] || [ "$SOLARIS_11" = "true" ] ; then
# shellcheck disable=SC2016
PARSE_6='($1 ~ "atch*") {nr[NR+3]} NR in nr {pgPageIn_PS=$3;}'
# shellcheck disable=SC2016
PARSE_7='($3 ~ "ppgout*") {nr2[NR+3]} NR in nr2 {pgPageOut_PS=$3}'
else
# shellcheck disable=SC2016
PARSE_6='($3 ~ "atch*") {nr[NR+3]} NR in nr {pgPageIn_PS=$5}'
# shellcheck disable=SC2016
PARSE_7='($3 ~ "pgout*") {nr2[NR+3]} NR in nr2 {pgPageOut_PS=$4}'
fi
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $PARSE_6 $PARSE_7 $DERIVE"
elif [ "$KERNEL" = "AIX" ] ; then
assertHaveCommand uptime
assertHaveCommand ps
assertHaveCommand vmstat
assertHaveCommandGivenPath /usr/sbin/lsps
assertHaveCommandGivenPath /usr/bin/svmon
# shellcheck disable=SC2016
CMD='eval uptime ; ps -e | wc -l ; ps -em | wc -l ; /usr/sbin/lsps -s ; vmstat 1 1 | tail -1 ; vmstat -s ; svmon; `dirname $0`/hardware.sh;'
# shellcheck disable=SC2016
PARSE_0='NR==1 {loadAvg1mi=0+$(NF-2)} NR==2 {processes=$1} NR==3 {threads=$1-processes }'
# ps -em inclundes processes with there threads ( at least one), so processes must be excluded to count threads #
# shellcheck disable=SC2016
PARSE_1='(NR==5) {swapUsedPercentage=substr( $NF, 1, length($NF)-1 )} (NR==6) {pgPageIn_PS=0+$(NF-13); pgPageOut_PS=0+$(NF-12)}'
# shellcheck disable=SC2016
PARSE_2='/^memory / {memTotalMB=$2 / 256 ; memFreeMB=$4 / 256}'
# shellcheck disable=SC2016
PARSE_3='/paging space page outs$/ {pgPageOut=$1 ; pgSwapOut="?" }'
# no pgSwapOut parameter and can't be monitored in AIX (by Jacky Ho, Systex)
# shellcheck disable=SC2016
PARSE_4='/cpu context switches$/ {cSwitches=$1} /device interrupts$/ {interrupts=$1 ; forks="?" }'
# shellcheck disable=SC2016
PARSE_5='/^CPU_COUNT/ {cpuCount=$2}'
DERIVE='END {memUsedMB=memTotalMB-memFreeMB; memUsedPct=(100.0*memUsedMB)/memTotalMB; memFreePct=100.0-memUsedPct; swapUsedPct=swapUsedPercentage ? swapUsedPercentage : 0; waitThreads=loadAvg1mi > cpuCount ? loadAvg1mi-cpuCount : 0}'
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $DERIVE"
elif [ "$KERNEL" = "HP-UX" ] ; then
assertHaveCommand uptime
assertHaveCommand ps
assertHaveCommand /usr/sbin/swapinfo
assertHaveCommand vmstat
# shellcheck disable=SC2016
CMD='eval uptime ; ps -e | wc -l ; /usr/sbin/swapinfo -m; vmstat -f; vmstat -s; `dirname $0`/hardware.sh; vmstat 1 2'
# shellcheck disable=SC2016
PARSE_0='NR==1 {loadAvg1mi=0+$(NF-2)} NR==2 {processes=$1} {threads="?"}'
# shellcheck disable=SC2016
PARSE_1='NR==5 {swapUsed=$3; swapFree=$4}'
# shellcheck disable=SC2016
PARSE_2='/^memory / {memTotalMB=$2; memUsedMB=$3; memFreeMB=$4}'
# shellcheck disable=SC2016
PARSE_3='(NR>=8 && $2=="forks,") {forks=$1}'
# shellcheck disable=SC2016
PARSE_4='/pages paged out$/ {pgPageOut=$1} /pages swapped out$/ {pgSwapOut=$1}'
# shellcheck disable=SC2016
PARSE_5='/interrupts$/ {interrupts=$1} /cpu context switches$/ {cSwitches=$1} /forks$/ {forks=$1}'
# shellcheck disable=SC2016
PARSE_6='/^CPU_COUNT/ {cpuCount=$2}'
# Sample output: http://ibgwww.colorado.edu/~lessem/psyc5112/usail/man/hpux/vmstat.1.html
# shellcheck disable=SC2016
PARSE_7='/^procs/ {nr[NR+3]} NR in nr {pgPageIn_PS=$8; pgPageOut_PS=$9; interrupts_PS=$13}'
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $PARSE_6 $PARSE_7 $DERIVE"
elif [ "$KERNEL" = "Darwin" ] ; then
assertHaveCommand sysctl
assertHaveCommand top
assertHaveCommand sar
# shellcheck disable=SC2016
CMD='eval sysctl hw.memsize ; sysctl vm.swapusage ; top -l 1 -n 0; `dirname $0`/hardware.sh; sar -gp 1 2'
FUNCS='function toMB(s) {n=0+s; if (index(s,"K")) {n /= 1024} if (index(s,"G")) {n *= 1024} return n}'
# shellcheck disable=SC2016
PARSE_0='/^hw.memsize:/ {memTotalMB=$2 / (1024*1024)}'
# shellcheck disable=SC2016
PARSE_1='/^PhysMem:/ {memFreeMB=toMB($6)+toMB($10)}' # we count "inactive" as "free", since it can be made available w/o a pagein/swapin
# shellcheck disable=SC2016
PARSE_2='/^vm.swapusage:/ {swapUsed=toMB($7); swapFree=toMB($10)}'
# shellcheck disable=SC2016
PARSE_3='/^VM:/ {pgPageOut=0+$7}'
if $OSX_GE_SNOW_LEOPARD; then
# shellcheck disable=SC2016
PARSE_4='/^Processes:/ {processes=$2; threads=$(NF-1)}'
else
# shellcheck disable=SC2016
PARSE_4='/^Processes:/ {processes=$2; threads=$(NF-2)}'
fi
# shellcheck disable=SC2016
PARSE_5='/^Load Avg:/ {loadAvg1mi=0+$3}'
# shellcheck disable=SC2016
PARSE_6='/^CPU_COUNT/ {cpuCount=$2}'
# shellcheck disable=SC2016
PARSE_7='($0 ~ "Average" && $1 ~ "pgout*") {next} {pgPageOut_PS=$2}'
# shellcheck disable=SC2016
PARSE_8='($0 ~ "Average" && $1 ~ "pgin*") {next} {pgPageIn_PS=$2}'
MASSAGE="$FUNCS $PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $PARSE_6 $PARSE_7 $PARSE_8 $DERIVE"
FILL_BLANKS='END {pgSwapOut=cSwitches=interrupts=interrupts_PS=forks="?"}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
# shellcheck disable=SC2016
CMD='eval sysctl hw.physmem ; vmstat -s ; top -Sb 0; `dirname $0`/hardware.sh'
FUNCS='function toMB(s) {n=0+s; if (index(s,"K")) {n /= 1024} if (index(s,"G")) {n *= 1024} return n}'
# shellcheck disable=SC2016
PARSE_0='(NR==1) {memTotalMB=$2 / (1024*1024)}'
# shellcheck disable=SC2016
PARSE_1='/pager pages paged out$/ {pgPageOut+=$1} /fork\(\) calls$/ {forks+=$1} /cpu context switches$/ {cSwitches+=$1} /interrupts$/ {interrupts+=$1}'
# shellcheck disable=SC2016
PARSE_2='/load averages:/ {loadAvg1mi=$6} /^[0-9]+ processes: / {processes=$1}'
# shellcheck disable=SC2016
PARSE_3='/^Swap: / {if(NF <= 5){ swapTotal=toMB($2); swapFree=toMB($4); swapUsed=swapTotal-swapFree; } else{ swapUsed=toMB($4); swapFree=toMB($6)}} /^Mem: / {memFreeMB=toMB($4)+toMB($12)}'
# shellcheck disable=SC2016
PARSE_4='/^CPU_COUNT/ {cpuCount=$2}'
# shellcheck disable=SC2016
PARSE_5='($3 ~ "INTR") {nr1[NR+3]} NR in nr1 {interrupts_PS=$3}'
# shellcheck disable=SC2016
PARSE_6='($3 ~ "pgpgin*") {nr2[NR+3]} NR in nr2 {pgPageIn_PS=$3; pgPageOut_PS=$4}'
MASSAGE="$FUNCS $PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $PARSE_6 $DERIVE"
FILL_BLANKS='END {threads=pgSwapOut="?"}'
fi
$CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $MASSAGE $FILL_BLANKS $PRINTF" header="$HEADER"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $MASSAGE $FILL_BLANKS $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"

193
bin/vmstat_metric.sh Executable file
View file

@ -0,0 +1,193 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
# hardware.sh is called in all commands to get CPU counts. The CPU count is required to determine
# the number of threads that waited for execution time. CPU count accounts for hyperthreaded cores so
# (load average - CPU count) gives a reasonable estimate of how many threads were waiting to execute.
HEADER='memTotalMB memFreeMB memUsedMB memFreePct memUsedPct pgPageOut swapUsedPct pgSwapOut cSwitches interrupts forks processes threads loadAvg1mi waitThreads interrupts_PS pgPageIn_PS pgPageOut_PS OSName OS_version IP_address'
HEADERIZE="BEGIN {print \"$HEADER\"}"
PRINTF='END {printf "%10d %10d %10d %10.1f %10.1f %10s %10.1f %10s %10s %10s %10s %10s %10s %10.2f %10.2f %13.2f %11.2f %12.2f %-35s %15s %-16s\n", memTotalMB, memFreeMB, memUsedMB, memFreePct, memUsedPct, pgPageOut, swapUsedPct, pgSwapOut, cSwitches, interrupts, forks, processes, threads, loadAvg1mi, waitThreads, interrupts_PS, pgPageIn_PS, pgPageOut_PS, OSName, OS_version, IP_address}'
DERIVE='END {memUsedMB=memTotalMB-memFreeMB; memUsedPct=(100.0*memUsedMB)/memTotalMB; memFreePct=100.0-memUsedPct; swapUsedPct=swapUsed ? (100.0*swapUsed)/(swapUsed+swapFree) : 0; waitThreads=loadAvg1mi > cpuCount ? loadAvg1mi-cpuCount : 0}'
FILL_DIMENSIONS='{length(IP_address) || IP_address = "?";length(OS_version) || OS_version = "?";length(OSName) || OSName = "?"}'
if [ "$KERNEL" = "Linux" ] ; then
assertHaveCommand uptime
assertHaveCommand ps
assertHaveCommand vmstat
assertHaveCommand sar
# shellcheck disable=SC2016
CMD='eval uptime ; ps -e | wc -l ; ps -eT | wc -l ; vmstat -s ; `dirname $0`/hardware.sh; sar -B 1 2; sar -I SUM 1 2'
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=$(hostname -I | cut -d\ -f1)"
else
DEFINE="-v OSName=$(cat /etc/*release | grep '\bNAME=' | cut -d '=' -f2 | tr ' ' '_' | cut -d\" -f2) -v OS_version=$(cat /etc/*release | grep '\bVERSION_ID=' | cut -d '=' -f2 | cut -d\" -f2) -v IP_address=$(hostname -I | cut -d\ -f1)"
fi
# shellcheck disable=SC2016
PARSE_0='NR==1 {loadAvg1mi=0+$(NF-2)} NR==2 {processes=$1} NR==3 {threads=$1}'
# shellcheck disable=SC2016
PARSE_1='/total memory$/ {memTotalMB=$1/1024} /free memory$/ {memFreeMB+=$1/1024} /buffer memory$/ {memFreeMB+=$1/1024} /swap cache$/ {memFreeMB+=$1/1024}'
# shellcheck disable=SC2016
PARSE_2='/pages paged out$/ {pgPageOut=$1} /used swap$/ {swapUsed=$1} /free swap$/ {swapFree=$1} /pages swapped out$/ {pgSwapOut=$1}'
# shellcheck disable=SC2016
PARSE_3='/interrupts$/ {interrupts=$1} /CPU context switches$/ {cSwitches=$1} /forks$/ {forks=$1}'
# shellcheck disable=SC2016
PARSE_4='/^CPU_COUNT/ {cpuCount=$2}'
# shellcheck disable=SC2016
PARSE_5='($3 ~ "INTR") {nr[NR+3]} NR in nr {interrupts_PS=$3}'
# shellcheck disable=SC2016
PARSE_6='($3 ~ "pgpgin*") {nr2[NR+3]} NR in nr2 {pgPageIn_PS=$2; pgPageOut_PS=$3}'
MESSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $PARSE_6 $DERIVE"
elif [ "$KERNEL" = "SunOS" ] ; then
assertHaveCommand vmstat
assertHaveCommandGivenPath /usr/sbin/swap
assertHaveCommandGivenPath /usr/sbin/prtconf
assertHaveCommand prstat
assertHaveCommand sar
if [ "$SOLARIS_8" = "true" ] || [ "$SOLARIS_9" = "true" ] ; then
# shellcheck disable=SC2016
CMD='eval /usr/sbin/prtconf 2>/dev/null | grep Memory ; /usr/sbin/swap -s ; vmstat 1 2 | sed "3d" ; vmstat -s ; prstat -n 1 1 1; `dirname $0`/hardware.sh; sar -gp 1 2; '
else
# shellcheck disable=SC2016
CMD='eval /usr/sbin/prtconf 2>/dev/null | grep Memory ; /usr/sbin/swap -s ; vmstat -q 1 2 | sed "3d" ; vmstat -s ; prstat -n 1 1 1; `dirname $0`/hardware.sh; sar -gp 1 2'
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)"
# shellcheck disable=SC2016
PARSE_0='/^Memory size:/ {memTotalMB=$3} (NR==5) {memFreeMB=$5 / 1024}'
# shellcheck disable=SC2016
PARSE_1='(NR==2) {swapUsed=0+$(NF-3); swapFree=0+$(NF-1)}'
# shellcheck disable=SC2016
PARSE_2='/pages paged out$/ {pgPageOut=$1} /pages swapped out$/ {pgSwapOut=$1}'
# shellcheck disable=SC2016
PARSE_3='/cpu context switches$/ {cSwitches=$1} /device interrupts$/ {interrupts=$1} / v?forks$/ {forks+=$1}'
# shellcheck disable=SC2016
PARSE_4='/^Total: / {processes=$2; threads=$4; loadAvg1mi=0+$(NF-2)}'
# shellcheck disable=SC2016
PARSE_5='/^CPU_COUNT/ {cpuCount=$2}'
# Sample output: http://opensolarisforum.org/man/man1/sar.html
if [ "$SOLARIS_10" = "true" ] || [ "$SOLARIS_11" = "true" ] ; then
# shellcheck disable=SC2016
PARSE_6='($1 ~ "atch*") {nr[NR+3]} NR in nr {pgPageIn_PS=$3;}'
# shellcheck disable=SC2016
PARSE_7='($3 ~ "ppgout*") {nr2[NR+3]} NR in nr2 {pgPageOut_PS=$3}'
else
# shellcheck disable=SC2016
PARSE_6='($3 ~ "atch*") {nr[NR+3]} NR in nr {pgPageIn_PS=$5}'
# shellcheck disable=SC2016
PARSE_7='($3 ~ "pgout*") {nr2[NR+3]} NR in nr2 {pgPageOut_PS=$4}'
fi
MESSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $PARSE_6 $PARSE_7 $DERIVE"
elif [ "$KERNEL" = "AIX" ] ; then
assertHaveCommand uptime
assertHaveCommand ps
assertHaveCommand vmstat
assertHaveCommandGivenPath /usr/sbin/lsps
assertHaveCommandGivenPath /usr/bin/svmon
# shellcheck disable=SC2016
CMD='eval uptime ; ps -e | wc -l ; ps -em | wc -l ; /usr/sbin/lsps -s ; vmstat 1 1 | tail -1 ; vmstat -s ; svmon; `dirname $0`/hardware.sh;'
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)"
# shellcheck disable=SC2016
PARSE_0='NR==1 {loadAvg1mi=0+$(NF-2)} NR==2 {processes=$1} NR==3 {threads=$1-processes }'
# ps -em inclundes processes with there threads ( at least one), so processes must be excluded to count threads #
# shellcheck disable=SC2016
PARSE_1='(NR==5) {swapUsedPercentage=substr( $NF, 1, length($NF)-1 )} (NR==6) {pgPageIn_PS=0+$(NF-13); pgPageOut_PS=0+$(NF-12)}'
# shellcheck disable=SC2016
PARSE_2='/^memory / {memTotalMB=$2 / 256 ; memFreeMB=$4 / 256}'
# shellcheck disable=SC2016
PARSE_3='/paging space page outs$/ {pgPageOut=$1 ; pgSwapOut="?" }'
# no pgSwapOut parameter and can't be monitored in AIX (by Jacky Ho, Systex)
# shellcheck disable=SC2016
PARSE_4='/cpu context switches$/ {cSwitches=$1} /device interrupts$/ {interrupts=$1 ; forks="?" }'
# shellcheck disable=SC2016
PARSE_5='/^CPU_COUNT/ {cpuCount=$2}'
PARSE_6='{OS_version=OSVersion/1000}'
DERIVE='END {memUsedMB=memTotalMB-memFreeMB; memUsedPct=(100.0*memUsedMB)/memTotalMB; memFreePct=100.0-memUsedPct; swapUsedPct=swapUsedPercentage ? swapUsedPercentage : 0; waitThreads=loadAvg1mi > cpuCount ? loadAvg1mi-cpuCount : 0}'
MESSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $PARSE_6 $DERIVE"
elif [ "$KERNEL" = "HP-UX" ] ; then
assertHaveCommand uptime
assertHaveCommand ps
assertHaveCommand /usr/sbin/swapinfo
assertHaveCommand vmstat
# shellcheck disable=SC2016
CMD='eval uptime ; ps -e | wc -l ; /usr/sbin/swapinfo -m; vmstat -f; vmstat -s; `dirname $0`/hardware.sh; vmstat 1 2'
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
PARSE_0='NR==1 {loadAvg1mi=0+$(NF-2)} NR==2 {processes=$1} {threads="?"}'
# shellcheck disable=SC2016
PARSE_1='NR==5 {swapUsed=$3; swapFree=$4}'
# shellcheck disable=SC2016
PARSE_2='/^memory / {memTotalMB=$2; memUsedMB=$3; memFreeMB=$4}'
# shellcheck disable=SC2016
PARSE_3='(NR>=8 && $2=="forks,") {forks=$1}'
# shellcheck disable=SC2016
PARSE_4='/pages paged out$/ {pgPageOut=$1} /pages swapped out$/ {pgSwapOut=$1}'
# shellcheck disable=SC2016
PARSE_5='/interrupts$/ {interrupts=$1} /cpu context switches$/ {cSwitches=$1} /forks$/ {forks=$1}'
# shellcheck disable=SC2016
PARSE_6='/^CPU_COUNT/ {cpuCount=$2}'
# Sample output: http://ibgwww.colorado.edu/~lessem/psyc5112/usail/man/hpux/vmstat.1.html
# shellcheck disable=SC2016
PARSE_7='/^procs/ {nr[NR+3]} NR in nr {pgPageIn_PS=$8; pgPageOut_PS=$9; interrupts_PS=$13}'
MESSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $PARSE_6 $PARSE_7 $DERIVE"
elif [ "$KERNEL" = "Darwin" ] ; then
assertHaveCommand sysctl
assertHaveCommand top
assertHaveCommand sar
# shellcheck disable=SC2016
CMD='eval sysctl hw.memsize ; sysctl vm.swapusage ; top -l 1 -n 0; `dirname $0`/hardware.sh; sar -gp 1 2'
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)"
FUNCS='function toMB(s) {n=0+s; if (index(s,"K")) {n /= 1024} if (index(s,"G")) {n *= 1024} return n}'
# shellcheck disable=SC2016
PARSE_0='/^hw.memsize:/ {memTotalMB=$2 / (1024*1024)}'
# shellcheck disable=SC2016
PARSE_1='/^PhysMem:/ {memFreeMB=toMB($6)+toMB($10)}' # we count "inactive" as "free", since it can be made available w/o a pagein/swapin
# shellcheck disable=SC2016
PARSE_2='/^vm.swapusage:/ {swapUsed=toMB($7); swapFree=toMB($10)}'
# shellcheck disable=SC2016
PARSE_3='/^VM:/ {pgPageOut=0+$7}'
if $OSX_GE_SNOW_LEOPARD; then
# shellcheck disable=SC2016
PARSE_4='/^Processes:/ {processes=$2; threads=$(NF-1)}'
else
# shellcheck disable=SC2016
PARSE_4='/^Processes:/ {processes=$2; threads=$(NF-2)}'
fi
# shellcheck disable=SC2016
PARSE_5='/^Load Avg:/ {loadAvg1mi=0+$3}'
# shellcheck disable=SC2016
PARSE_6='/^CPU_COUNT/ {cpuCount=$2}'
# shellcheck disable=SC2016
PARSE_7='($0 ~ "Average" && $1 ~ "pgout*") {next} {pgPageOut_PS=$2}'
# shellcheck disable=SC2016
PARSE_8='($0 ~ "Average" && $1 ~ "pgin*") {next} {pgPageIn_PS=$2}'
MESSAGE="$FUNCS $PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $PARSE_6 $PARSE_7 $PARSE_8 $DERIVE"
FILL_BLANKS='END {pgSwapOut=cSwitches=interrupts=interrupts_PS=forks="?"}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
# shellcheck disable=SC2016
CMD='eval sysctl hw.physmem ; vmstat -s ; top -Sb 0; `dirname $0`/hardware.sh'
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)"
FUNCS='function toMB(s) {n=0+s; if (index(s,"K")) {n /= 1024} if (index(s,"G")) {n *= 1024} return n}'
# shellcheck disable=SC2016
PARSE_0='(NR==1) {memTotalMB=$2 / (1024*1024)}'
# shellcheck disable=SC2016
PARSE_1='/pager pages paged out$/ {pgPageOut+=$1} /fork\(\) calls$/ {forks+=$1} /cpu context switches$/ {cSwitches+=$1} /interrupts$/ {interrupts+=$1}'
# shellcheck disable=SC2016
PARSE_2='/load averages:/ {loadAvg1mi=$6} /^[0-9]+ processes: / {processes=$1}'
# shellcheck disable=SC2016
PARSE_3='/^Swap: / {if(NF <= 5){ swapTotal=toMB($2); swapFree=toMB($4); swapUsed=swapTotal-swapFree; } else{ swapUsed=toMB($4); swapFree=toMB($6)}} /^Mem: / {memFreeMB=toMB($4)+toMB($12)}'
# shellcheck disable=SC2016
PARSE_4='/^CPU_COUNT/ {cpuCount=$2}'
# shellcheck disable=SC2016
PARSE_5='($3 ~ "INTR") {nr1[NR+3]} NR in nr1 {interrupts_PS=$3}'
# shellcheck disable=SC2016
PARSE_6='($3 ~ "pgpgin*") {nr2[NR+3]} NR in nr2 {pgPageIn_PS=$3; pgPageOut_PS=$4}'
MESSAGE="$FUNCS $PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4 $PARSE_5 $PARSE_6 $DERIVE"
FILL_BLANKS='END {threads=pgSwapOut="?"}'
fi
# shellcheck disable=SC2086
$CMD | tee "$TEE_DEST" | $AWK $DEFINE "$HEADERIZE $MESSAGE $FILL_BLANKS $FILL_DIMENSIONS $PRINTF " header="$HEADER"
echo "Cmd = [$CMD]; | $AWK $DEFINE '$HEADERIZE $MESSAGE $FILL_BLANKS $FILL_DIMENSIONS $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"

65
bin/vsftpdChecker.sh Executable file
View file

@ -0,0 +1,65 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
# VSFTPD configuration file format is common to all platforms, but may be in one
# of several locations (and may also be restricted to root).
if [ -f /etc/vsftpd.conf ] ; then
VSFTPD_CONFIG_FILE=/etc/vsftpd.conf
elif [ -f /etc/vsftpd/vsftpd.conf ] ; then
VSFTPD_CONFIG_FILE=/etc/vsftpd/vsftpd.conf
elif [ -f /private/etc/vsftpd.conf ] ; then
# Usually MAC OS X
VSFTPD_CONFIG_FILE=/private/etc/vsftpd.conf
elif [ -f /usr/local/etc/vsftpd.conf ] ; then
# To support MAC OS 10.15
VSFTPD_CONFIG_FILE=/usr/local/etc/vsftpd.conf
fi
# Set the default. If the file is readable and has "anonymous_enable" commented
# out, the default behavior is to ALLOW anonymous FTP. Reset the value of
# anonymous_enable in the output if this is the case
# line, then the allowed protocols will be the default of "2,1".
FILL_BLANKS='END {
if (ANON_DEFAULT != 0) {
ANON_ENABLE=ANON_DEFAULT
}'
PRINTF='{printf "%s app=vsftp %s %s %s\n", DATE, FILEHASH, LOCAL_ENABLE, ANON_ENABLE}}'
# If $VSFTPD_CONFIG_FILE file exists and is a regular file.
if [ -f "$VSFTPD_CONFIG_FILE" ] ; then
assertHaveCommand cat
assertHaveCommand date
# Get file hash
# shellcheck disable=SC2016
CMD='eval date ; eval LD_LIBRARY_PATH=$SPLUNK_HOME/lib $SPLUNK_HOME/bin/openssl sha256 $VSFTPD_CONFIG_FILE ; cat $VSFTPD_CONFIG_FILE'
# Get the date.
# shellcheck disable=SC2016
PARSE_0='NR==1 {DATE=$0}'
# Try to use cross-platform case-insensitive matching for text. Note
# that "match", "tolower", IGNORECASE and other common awk commands or
# options are actually nawk/gawk extensions so avoid them if possible.
# shellcheck disable=SC2016
PARSE_1='/[Ll][Oo][Cc][Aa][Ll][_][Ee][Nn][Aa][Bb][Ll][Ee]/ { split($0, arr, "=") ; LOCAL_ENABLE="local_enable=" arr[2] } '
# shellcheck disable=SC2016
PARSE_2='/^[Aa][Nn][Oo][Nn][Yy][Mm][Oo][Uu][Ss][_][Ee][Nn][Aa][Bb][Ll][Ee]/ { split($0, arr, "=") ; ANON_ENABLE="anonymous_enable=" arr[2] } '
# The default behavior is to permit anonymous FTP
PARSE_3='/^[#]+[[:blank:]]*[Aa][Nn][Oo][Nn][Yy][Mm][Oo][Uu][Ss][_][Ee][Nn][Aa][Bb][Ll][Ee]/ { ANON_DEFAULT="anonymous_enable=YES"} '
# shellcheck disable=SC2016
PARSE_4='/^SHA256/ {FILEHASH="file_hash=" $2}'
MASSAGE="$PARSE_0 $PARSE_1 $PARSE_2 $PARSE_3 $PARSE_4"
$CMD | tee "$TEE_DEST" | $AWK "$MASSAGE $FILL_BLANKS $PRINTF"
echo "Cmd = [$CMD]; | $AWK '$MASSAGE $FILL_BLANKS $PRINTF'" >> "$TEE_DEST"
else
echo "VSFTPD configuration file not found." >> "$TEE_DEST"
fi

41
bin/who.sh Executable file
View file

@ -0,0 +1,41 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2024 Splunk, Inc.
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC1091
. "$(dirname "$0")"/common.sh
CMD='who -H'
HEADER='USERNAME LINE HOSTNAME TIME'
# shellcheck disable=SC2016
HEADERIZE='{NR == 1 && $0 = header}'
# shellcheck disable=SC2016
FORMAT='{length(hostname) || hostname=$NF; gsub("[)(]", "",hostname); time=$3; for (i=4; i<=lastTimeColumn; i++) time = time " " $i}'
# shellcheck disable=SC2016
PRINTF='{if (NR == 1) {print $0} else {printf "%-14s %-10s %-40.40s %-s\n", $1,$2,hostname,time}}'
if [ "$KERNEL" = "Linux" ] ; then
FILL_BLANKS='{hostname = ""; lastTimeColumn = NF-1; if (NF < 5) {hostname = "<console>"; lastTimeColumn = NF}}'
elif [ "$KERNEL" = "SunOS" ] ; then
FILL_BLANKS='{hostname = ""; lastTimeColumn = NF-1; if (NF < 6) {hostname = "<console>"; lastTimeColumn = NF}}'
elif [ "$KERNEL" = "AIX" ] ; then
FILL_BLANKS='{hostname = ""; lastTimeColumn = NF-1; if (NF < 6) {hostname = "<console>"; lastTimeColumn = NF}}'
elif [ "$KERNEL" = "HP-UX" ] ; then
CMD='who -HR'
FILL_BLANKS='{hostname = ""; lastTimeColumn = NF-1; if (NF < 5) {hostname = "<console>"; lastTimeColumn = NF}}'
elif [ "$KERNEL" = "Darwin" ] ; then
FILL_BLANKS='{hostname = ""; lastTimeColumn = NF-1; if (NF < 6) {hostname = "<console>"; lastTimeColumn = NF}}'
elif [ "$KERNEL" = "FreeBSD" ] ; then
FILL_BLANKS='{hostname = ""; lastTimeColumn = NF-1; if (NF < 6) {hostname = "<console>"; lastTimeColumn = NF}}'
fi
assertHaveCommand "$CMD"
out=$($CMD | tee "$TEE_DEST" | $AWK "$HEADERIZE $FILL_BLANKS $FORMAT $PRINTF" header="$HEADER")
lines=$(echo "$out" | wc -l)
if [ "$lines" -gt 1 ]; then
echo "$out"
echo "Cmd = [$CMD]; | $AWK '$HEADERIZE $FILL_BLANKS $FORMAT $PRINTF' header=\"$HEADER\"" >> "$TEE_DEST"
else
echo "No data is present" >> "$TEE_DEST"
fi